mirror of
https://github.com/jeffvli/sonixd.git
synced 2026-04-29 18:52:38 -04:00
Make scrobbling configurable, clean up logic (#17)
This commit is contained in:
@@ -44,6 +44,7 @@ const playQueueState: PlayQueue = {
|
||||
playerUpdated: 0,
|
||||
autoIncremented: false,
|
||||
volume: 0.5,
|
||||
scrobble: false,
|
||||
isLoading: false,
|
||||
repeat: 'all',
|
||||
shuffle: false,
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
setFadeData,
|
||||
setPlayerSrc,
|
||||
} from '../../redux/playQueueSlice';
|
||||
import { setCurrentSeek, setScrobbled } from '../../redux/playerSlice';
|
||||
import { setCurrentSeek } from '../../redux/playerSlice';
|
||||
import cacheSong from '../shared/cacheSong';
|
||||
import { getSongCachePath, isCached } from '../../shared/utils';
|
||||
import { scrobble } from '../../api/api';
|
||||
@@ -35,7 +35,9 @@ const gaplessListenHandler = (
|
||||
currentPlayer: number,
|
||||
dispatch: any,
|
||||
pollingInterval: number,
|
||||
scrobbled: boolean
|
||||
shouldScrobble: boolean,
|
||||
scrobbled: boolean,
|
||||
setScrobbled: any
|
||||
) => {
|
||||
const currentSeek = currentPlayerRef.current?.audioEl.current?.currentTime || 0;
|
||||
const duration = currentPlayerRef.current?.audioEl.current?.duration;
|
||||
@@ -55,8 +57,19 @@ const gaplessListenHandler = (
|
||||
nextPlayerRef.current.audioEl.current.play();
|
||||
}
|
||||
|
||||
if ((currentSeek >= 240 || currentSeek >= duration - 5) && !scrobbled) {
|
||||
dispatch(setScrobbled(true));
|
||||
// Conditions for scrobbling gapless track
|
||||
// 1. Scrobble enabled in settings
|
||||
// 2. Not already scrobbled
|
||||
// 3. Track reached past 4 minutes or past the 90% mark
|
||||
// 4. Not in the last 2 seconds of the track (gapless player starts second track before first ends)
|
||||
// Step 4 sets the scrobbled value to false again which would trigger a second scrobble
|
||||
if (
|
||||
shouldScrobble &&
|
||||
!scrobbled &&
|
||||
(currentSeek >= 240 || currentSeek >= duration * 0.9) &&
|
||||
currentSeek <= duration - 2
|
||||
) {
|
||||
setScrobbled(true);
|
||||
scrobble({ id: playQueue.currentSongId, submission: true });
|
||||
}
|
||||
};
|
||||
@@ -72,7 +85,9 @@ const listenHandler = (
|
||||
fadeType: string,
|
||||
volumeFade: boolean,
|
||||
debug: boolean,
|
||||
scrobbled: boolean
|
||||
shouldScrobble: boolean,
|
||||
scrobbled: boolean,
|
||||
setScrobbled: any
|
||||
) => {
|
||||
const currentSeek = currentPlayerRef.current?.audioEl.current?.currentTime || 0;
|
||||
const duration = currentPlayerRef.current?.audioEl.current?.duration;
|
||||
@@ -203,12 +218,18 @@ const listenHandler = (
|
||||
dispatch(setCurrentSeek({ seek: currentSeek }));
|
||||
}
|
||||
|
||||
// Conditions for scrobbling fading track
|
||||
// 1. Scrobble enabled in settings
|
||||
// 2. Not already scrobbled
|
||||
// 3. Track reached past 4 minutes or past the fadeAtTime - 15 seconds
|
||||
// 4. The track is not fading
|
||||
if (
|
||||
(currentSeek >= 240 || currentSeek >= duration - fadeAtTime + 1) &&
|
||||
shouldScrobble &&
|
||||
!scrobbled &&
|
||||
(currentSeek >= 240 || currentSeek >= fadeAtTime - 15) &&
|
||||
currentSeek <= fadeAtTime
|
||||
) {
|
||||
dispatch(setScrobbled(true));
|
||||
setScrobbled(true);
|
||||
scrobble({ id: playQueue.currentSongId, submission: true });
|
||||
}
|
||||
};
|
||||
@@ -227,6 +248,7 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
const [fadeType, setFadeType] = useState(playQueue.fadeType);
|
||||
const [volumeFade, setVolumeFade] = useState(playQueue.volumeFade);
|
||||
const [pollingInterval, setPollingInterval] = useState(playQueue.pollingInterval);
|
||||
const [scrobbled, setScrobbled] = useState(false);
|
||||
|
||||
const getSrc1 = useCallback(() => {
|
||||
const cachedSongPath = `${cachePath}/${
|
||||
@@ -347,18 +369,11 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
fadeType,
|
||||
volumeFade,
|
||||
debug,
|
||||
player.scrobbled
|
||||
playQueue.scrobble,
|
||||
scrobbled,
|
||||
setScrobbled
|
||||
);
|
||||
}, [
|
||||
currentEntryList,
|
||||
debug,
|
||||
dispatch,
|
||||
fadeDuration,
|
||||
fadeType,
|
||||
playQueue,
|
||||
player.scrobbled,
|
||||
volumeFade,
|
||||
]);
|
||||
}, [currentEntryList, debug, dispatch, fadeDuration, fadeType, playQueue, scrobbled, volumeFade]);
|
||||
|
||||
const handleListenPlayer2 = useCallback(() => {
|
||||
listenHandler(
|
||||
@@ -372,18 +387,11 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
fadeType,
|
||||
volumeFade,
|
||||
debug,
|
||||
player.scrobbled
|
||||
playQueue.scrobble,
|
||||
scrobbled,
|
||||
setScrobbled
|
||||
);
|
||||
}, [
|
||||
currentEntryList,
|
||||
debug,
|
||||
dispatch,
|
||||
fadeDuration,
|
||||
fadeType,
|
||||
playQueue,
|
||||
player.scrobbled,
|
||||
volumeFade,
|
||||
]);
|
||||
}, [currentEntryList, debug, dispatch, fadeDuration, fadeType, playQueue, scrobbled, volumeFade]);
|
||||
|
||||
const handleOnEndedPlayer1 = () => {
|
||||
player1Ref.current.audioEl.current.currentTime = 0;
|
||||
@@ -452,7 +460,7 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleGaplessPlayer1 = () => {
|
||||
const handleGaplessPlayer1 = useCallback(() => {
|
||||
gaplessListenHandler(
|
||||
player1Ref,
|
||||
player2Ref,
|
||||
@@ -460,11 +468,13 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
1,
|
||||
dispatch,
|
||||
pollingInterval,
|
||||
player.scrobbled
|
||||
playQueue.scrobble,
|
||||
scrobbled,
|
||||
setScrobbled
|
||||
);
|
||||
};
|
||||
}, [dispatch, playQueue, scrobbled, pollingInterval]);
|
||||
|
||||
const handleGaplessPlayer2 = () => {
|
||||
const handleGaplessPlayer2 = useCallback(() => {
|
||||
gaplessListenHandler(
|
||||
player2Ref,
|
||||
player1Ref,
|
||||
@@ -472,13 +482,27 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
2,
|
||||
dispatch,
|
||||
pollingInterval,
|
||||
player.scrobbled
|
||||
playQueue.scrobble,
|
||||
scrobbled,
|
||||
setScrobbled
|
||||
);
|
||||
};
|
||||
}, [dispatch, playQueue, scrobbled, pollingInterval]);
|
||||
|
||||
const handleOnPlay = () => {
|
||||
dispatch(setScrobbled(false));
|
||||
scrobble({ id: playQueue.currentSongId, submission: false });
|
||||
const handleOnPlay = (playerNumber: 1 | 2) => {
|
||||
setScrobbled(false);
|
||||
if (playQueue.scrobble) {
|
||||
if (playerNumber === 1) {
|
||||
scrobble({
|
||||
id: playQueue[currentEntryList][playQueue.player1.index].id,
|
||||
submission: false,
|
||||
});
|
||||
} else {
|
||||
scrobble({
|
||||
id: playQueue[currentEntryList][playQueue.player2.index].id,
|
||||
submission: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -490,7 +514,7 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
<ReactAudioPlayer
|
||||
ref={player1Ref}
|
||||
src={playQueue.player1.src}
|
||||
onPlay={handleOnPlay}
|
||||
onPlay={() => handleOnPlay(1)}
|
||||
listenInterval={pollingInterval}
|
||||
preload="auto"
|
||||
onListen={fadeDuration === 0 ? handleGaplessPlayer1 : handleListenPlayer1}
|
||||
@@ -512,7 +536,7 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
|
||||
<ReactAudioPlayer
|
||||
ref={player2Ref}
|
||||
src={playQueue.player2.src}
|
||||
onPlay={handleOnPlay}
|
||||
onPlay={() => handleOnPlay(2)}
|
||||
listenInterval={pollingInterval}
|
||||
preload="auto"
|
||||
onListen={fadeDuration === 0 ? handleGaplessPlayer2 : handleListenPlayer2}
|
||||
|
||||
@@ -3,11 +3,15 @@ import settings from 'electron-settings';
|
||||
import { ControlLabel } from 'rsuite';
|
||||
import { ConfigPanel } from '../styled';
|
||||
import { StyledCheckbox, StyledInputNumber } from '../../shared/styled';
|
||||
import { useAppDispatch } from '../../../redux/hooks';
|
||||
import { setPlaybackSetting } from '../../../redux/playQueueSlice';
|
||||
|
||||
const PlayerConfig = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const [globalMediaHotkeys, setGlobalMediaHotkeys] = useState(
|
||||
Boolean(settings.getSync('globalMediaHotkeys'))
|
||||
);
|
||||
const [scrobble, setScrobble] = useState(Boolean(settings.getSync('scrobble')));
|
||||
return (
|
||||
<ConfigPanel header="Player" bordered>
|
||||
<p>
|
||||
@@ -48,6 +52,16 @@ const PlayerConfig = () => {
|
||||
>
|
||||
Enable global media hotkeys (requires app restart)
|
||||
</StyledCheckbox>
|
||||
<StyledCheckbox
|
||||
defaultChecked={scrobble}
|
||||
onChange={() => {
|
||||
settings.setSync('scrobble', !scrobble);
|
||||
dispatch(setPlaybackSetting({ setting: 'scrobble', value: !scrobble }));
|
||||
setScrobble(!scrobble);
|
||||
}}
|
||||
>
|
||||
Enable scrobbling
|
||||
</StyledCheckbox>
|
||||
</ConfigPanel>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,6 +26,10 @@ const setDefaultSettings = (force: boolean) => {
|
||||
settings.setSync('cachePath', path.join(path.dirname(settings.file())));
|
||||
}
|
||||
|
||||
if (force || !settings.hasSync('scrobble')) {
|
||||
settings.setSync('scrobble', false);
|
||||
}
|
||||
|
||||
if (force || !settings.hasSync('volume')) {
|
||||
settings.setSync('volume', 0.3);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ export interface PlayQueue {
|
||||
playerUpdated: number;
|
||||
autoIncremented: boolean;
|
||||
volume: number;
|
||||
scrobble: boolean;
|
||||
isLoading: boolean;
|
||||
repeat: string;
|
||||
shuffle: boolean;
|
||||
@@ -119,6 +120,7 @@ const initialState: PlayQueue = {
|
||||
playerUpdated: 0,
|
||||
autoIncremented: false,
|
||||
volume: Number(parsedSettings.volume),
|
||||
scrobble: Boolean(parsedSettings.scrobble),
|
||||
isLoading: Boolean(false),
|
||||
repeat: String(parsedSettings.repeat),
|
||||
shuffle: Boolean(parsedSettings.shuffle),
|
||||
@@ -302,6 +304,9 @@ const playQueueSlice = createSlice({
|
||||
case 'scrollWithCurrentSong':
|
||||
state.scrollWithCurrentSong = action.payload.value;
|
||||
break;
|
||||
case 'scrobble':
|
||||
state.scrobble = action.payload.value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export const mockSettings = {
|
||||
pollingInterval: 20,
|
||||
fadeDuration: 9,
|
||||
fadeType: 'equalPower',
|
||||
scrobble: false,
|
||||
gridCardSize: 200,
|
||||
playlistViewType: 'grid',
|
||||
albumViewType: 'grid',
|
||||
|
||||
Reference in New Issue
Block a user