diff --git a/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx b/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx index ac6251722..b5f1ef8ec 100644 --- a/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx +++ b/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx @@ -1,5 +1,4 @@ import { UseSuspenseQueryOptions } from '@tanstack/react-query'; -import { ref } from 'process'; import { api } from '/@/renderer/api'; import { useItemListPaginatedLoader } from '/@/renderer/components/item-list/helpers/item-list-paginated-loader'; @@ -77,7 +76,6 @@ export const AlbumArtistListPaginatedGrid = ({ itemsPerRow={itemsPerRow} itemType={LibraryItem.ALBUM_ARTIST} onScrollEnd={handleOnScrollEnd} - ref={ref} rows={rows} /> diff --git a/src/renderer/features/player/audio-player/engine/web-player-engine.tsx b/src/renderer/features/player/audio-player/engine/web-player-engine.tsx index cf81cb25f..f2824d7f0 100644 --- a/src/renderer/features/player/audio-player/engine/web-player-engine.tsx +++ b/src/renderer/features/player/audio-player/engine/web-player-engine.tsx @@ -1,6 +1,6 @@ import type { RefObject } from 'react'; -import { useEffect, useImperativeHandle, useRef, useState } from 'react'; +import { useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; import ReactPlayer from 'react-player'; import { AudioPlayer, PlayerOnProgressProps } from '/@/renderer/features/player/audio-player/types'; @@ -153,15 +153,37 @@ export const WebPlayerEngine = (props: WebPlayerEngineProps) => { useEffect(() => { const player1 = player1Ref.current?.getInternalPlayer(); - if (player1) { + if (player1 && player1 instanceof HTMLAudioElement) { player1.preservesPitch = preservesPitch; } const player2 = player2Ref.current?.getInternalPlayer(); - if (player2) { + if (player2 && player2 instanceof HTMLAudioElement) { player2.preservesPitch = preservesPitch; } }, [preservesPitch]); + const handleOnReadyPlayer1 = useCallback( + (player: ReactPlayer) => { + const internal = player.getInternalPlayer(); + if (internal && internal instanceof HTMLAudioElement) { + internal.preservesPitch = preservesPitch; + } + onStartedPlayer1(player); + }, + [onStartedPlayer1, preservesPitch], + ); + + const handleOnReadyPlayer2 = useCallback( + (player: ReactPlayer) => { + const internal = player.getInternalPlayer(); + if (internal && internal instanceof HTMLAudioElement) { + internal.preservesPitch = preservesPitch; + } + onStartedPlayer2(player); + }, + [onStartedPlayer2, preservesPitch], + ); + return (
{ onEnded={src1 ? () => onEndedPlayer1() : undefined} onError={handleOnError(player1Ref, () => onEndedPlayer1())} onProgress={onProgressPlayer1} - onReady={onStartedPlayer1} + onReady={handleOnReadyPlayer1} playbackRate={speed || 1} playing={playerNum === 1 && playerStatus === PlayerStatus.PLAYING} progressInterval={isTransitioning ? 10 : 250} @@ -195,7 +217,7 @@ export const WebPlayerEngine = (props: WebPlayerEngineProps) => { onEnded={src2 ? () => onEndedPlayer2() : undefined} onError={handleOnError(player2Ref, () => onEndedPlayer2())} onProgress={onProgressPlayer2} - onReady={onStartedPlayer2} + onReady={handleOnReadyPlayer2} playbackRate={speed || 1} playing={playerNum === 2 && playerStatus === PlayerStatus.PLAYING} progressInterval={isTransitioning ? 10 : 250} diff --git a/src/renderer/features/player/components/player-config.tsx b/src/renderer/features/player/components/player-config.tsx index 907d2c23a..2af16223f 100644 --- a/src/renderer/features/player/components/player-config.tsx +++ b/src/renderer/features/player/components/player-config.tsx @@ -1,5 +1,5 @@ import isElectron from 'is-electron'; -import { useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ListConfigTable } from '/@/renderer/features/shared/components/list-config-menu'; @@ -11,12 +11,17 @@ import { usePlayerSpeed, usePlayerStatus, } from '/@/renderer/store'; -import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store'; +import { + usePlaybackSettings, + useSettingsStore, + useSettingsStoreActions, +} from '/@/renderer/store/settings.store'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { Popover } from '/@/shared/components/popover/popover'; import { SegmentedControl } from '/@/shared/components/segmented-control/segmented-control'; import { Select } from '/@/shared/components/select/select'; import { Slider } from '/@/shared/components/slider/slider'; +import { Switch } from '/@/shared/components/switch/switch'; import { toast } from '/@/shared/components/toast/toast'; import { CrossfadeStyle, @@ -42,9 +47,20 @@ export const PlayerConfig = () => { const { crossfadeDuration, crossfadeStyle, transitionType } = usePlayerProperties(); const { setCrossfadeDuration, setCrossfadeStyle, setQueueType, setSpeed, setTransitionType } = usePlayerActions(); + const preservePitch = useSettingsStore((state) => state.playback.preservePitch); + const playbackSettings = usePlaybackSettings(); const { setSettings } = useSettingsStoreActions(); + const setPreservePitch = useCallback( + (value: boolean) => { + setSettings({ + playback: { ...playbackSettings, preservePitch: value }, + }); + }, + [playbackSettings, setSettings], + ); + const [audioDevices, setAudioDevices] = useState<{ label: string; value: string }[]>([]); useEffect(() => { @@ -288,26 +304,38 @@ export const PlayerConfig = () => { id: 'playbackSpeed', label: t('player.playbackSpeed', { postProcess: 'titleCase' }), }, + { + component: ( + setPreservePitch(e.currentTarget.checked)} + /> + ), + id: 'preservePitch', + label: t('setting.preservePitch', { postProcess: 'titleCase' }), + }, ]; return allOptions; }, [ - playbackSettings, - audioDevices, - status, - setSettings, - currentSong, - speed, - setSpeed, + t, queueType, - setQueueType, + playbackSettings, + status, + audioDevices, transitionType, - setTransitionType, + crossfadeStyle, crossfadeDuration, setCrossfadeDuration, - crossfadeStyle, + speed, + setSpeed, + preservePitch, + currentSong?.bpm, + setQueueType, + setSettings, + setTransitionType, setCrossfadeStyle, - t, + setPreservePitch, ]); return (