[bugfix]: fix scrobble race conditions
This commit is contained in:
parent
2854a91700
commit
ab17ba8add
1 changed files with 21 additions and 5 deletions
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useCallback, useState, useRef } from 'react';
|
import { useEffect, useCallback, useState, useRef } from 'react';
|
||||||
import { QueueSong, ServerType } from '/@/renderer/api/types';
|
import { QueueSong, ServerType } from '/@/renderer/api/types';
|
||||||
import { useSendScrobble } from '/@/renderer/features/player/mutations/scrobble-mutation';
|
import { useSendScrobble } from '/@/renderer/features/player/mutations/scrobble-mutation';
|
||||||
import { useCurrentStatus, usePlayerStore } from '/@/renderer/store';
|
import { usePlayerStore } from '/@/renderer/store';
|
||||||
import { usePlaybackSettings } from '/@/renderer/store/settings.store';
|
import { usePlaybackSettings } from '/@/renderer/store/settings.store';
|
||||||
import { PlayerStatus } from '/@/renderer/types';
|
import { PlayerStatus } from '/@/renderer/types';
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ const checkScrobbleConditions = (args: {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useScrobble = () => {
|
export const useScrobble = () => {
|
||||||
const status = useCurrentStatus();
|
|
||||||
const scrobbleSettings = usePlaybackSettings().scrobble;
|
const scrobbleSettings = usePlaybackSettings().scrobble;
|
||||||
const isScrobbleEnabled = scrobbleSettings?.enabled;
|
const isScrobbleEnabled = scrobbleSettings?.enabled;
|
||||||
const sendScrobble = useSendScrobble();
|
const sendScrobble = useSendScrobble();
|
||||||
|
@ -94,6 +93,7 @@ export const useScrobble = () => {
|
||||||
|
|
||||||
if (progressIntervalId.current) {
|
if (progressIntervalId.current) {
|
||||||
clearInterval(progressIntervalId.current);
|
clearInterval(progressIntervalId.current);
|
||||||
|
progressIntervalId.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const currentSong = current[0] as QueueSong | undefined;
|
// const currentSong = current[0] as QueueSong | undefined;
|
||||||
|
@ -135,9 +135,13 @@ export const useScrobble = () => {
|
||||||
clearTimeout(songChangeTimeoutId.current as ReturnType<typeof setTimeout>);
|
clearTimeout(songChangeTimeoutId.current as ReturnType<typeof setTimeout>);
|
||||||
songChangeTimeoutId.current = setTimeout(() => {
|
songChangeTimeoutId.current = setTimeout(() => {
|
||||||
const currentSong = current[0] as QueueSong | undefined;
|
const currentSong = current[0] as QueueSong | undefined;
|
||||||
|
// Get the current status from the state, not variable. This is because
|
||||||
|
// of a timing issue where, when playing the first track, the first
|
||||||
|
// event is song, and then the event is play
|
||||||
|
const currentStatus = usePlayerStore.getState().current.status;
|
||||||
|
|
||||||
// Send start scrobble when song changes and the new song is playing
|
// Send start scrobble when song changes and the new song is playing
|
||||||
if (status === PlayerStatus.PLAYING && currentSong?.id) {
|
if (currentStatus === PlayerStatus.PLAYING && currentSong?.id) {
|
||||||
sendScrobble.mutate({
|
sendScrobble.mutate({
|
||||||
query: {
|
query: {
|
||||||
event: 'start',
|
event: 'start',
|
||||||
|
@ -149,6 +153,12 @@ export const useScrobble = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentSong?.serverType === ServerType.JELLYFIN) {
|
if (currentSong?.serverType === ServerType.JELLYFIN) {
|
||||||
|
// It is possible that another function sets an interval.
|
||||||
|
// We only want one running, so clear the existing interval
|
||||||
|
if (progressIntervalId.current) {
|
||||||
|
clearInterval(progressIntervalId.current);
|
||||||
|
}
|
||||||
|
|
||||||
progressIntervalId.current = setInterval(() => {
|
progressIntervalId.current = setInterval(() => {
|
||||||
const currentTime = usePlayerStore.getState().current.time;
|
const currentTime = usePlayerStore.getState().current.time;
|
||||||
handleScrobbleFromSeek(currentTime);
|
handleScrobbleFromSeek(currentTime);
|
||||||
|
@ -163,7 +173,6 @@ export const useScrobble = () => {
|
||||||
scrobbleSettings?.scrobbleAtPercentage,
|
scrobbleSettings?.scrobbleAtPercentage,
|
||||||
isCurrentSongScrobbled,
|
isCurrentSongScrobbled,
|
||||||
sendScrobble,
|
sendScrobble,
|
||||||
status,
|
|
||||||
handleScrobbleFromSeek,
|
handleScrobbleFromSeek,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -200,8 +209,14 @@ export const useScrobble = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentSong?.serverType === ServerType.JELLYFIN) {
|
if (currentSong?.serverType === ServerType.JELLYFIN) {
|
||||||
|
// It is possible that another function sets an interval.
|
||||||
|
// We only want one running, so clear the existing interval
|
||||||
|
if (progressIntervalId.current) {
|
||||||
|
clearInterval(progressIntervalId.current);
|
||||||
|
}
|
||||||
|
|
||||||
progressIntervalId.current = setInterval(() => {
|
progressIntervalId.current = setInterval(() => {
|
||||||
const currentTime = currentTimeSec;
|
const currentTime = usePlayerStore.getState().current.time;
|
||||||
handleScrobbleFromSeek(currentTime);
|
handleScrobbleFromSeek(currentTime);
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
|
@ -220,6 +235,7 @@ export const useScrobble = () => {
|
||||||
|
|
||||||
if (progressIntervalId.current) {
|
if (progressIntervalId.current) {
|
||||||
clearInterval(progressIntervalId.current as ReturnType<typeof setInterval>);
|
clearInterval(progressIntervalId.current as ReturnType<typeof setInterval>);
|
||||||
|
progressIntervalId.current = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const isLastTrackInQueue = usePlayerStore.getState().actions.checkIsLastTrack();
|
const isLastTrackInQueue = usePlayerStore.getState().actions.checkIsLastTrack();
|
||||||
|
|
Reference in a new issue