mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-27 02:37:21 +01:00
A playlistTrack id is a position in the playlist, not a stable key, so refetching a row by id after the annotation is saved can return a different song: in a smart playlist filtered on that annotation the track is gone and every later row has shifted up. The stale-keyed record then renders as a duplicate of its neighbour. Signed-off-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com> Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com> Co-authored-by: Deluan Quintão <deluan@navidrome.org>
63 lines
1.9 KiB
JavaScript
63 lines
1.9 KiB
JavaScript
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
import { useDataProvider, useNotify, useRefresh } from 'react-admin'
|
|
import subsonic from '../subsonic'
|
|
|
|
export const useToggleLove = (resource, record = {}) => {
|
|
const [loading, setLoading] = useState(false)
|
|
const notify = useNotify()
|
|
|
|
const mountedRef = useRef(false)
|
|
useEffect(() => {
|
|
mountedRef.current = true
|
|
return () => {
|
|
mountedRef.current = false
|
|
}
|
|
}, [])
|
|
|
|
const dataProvider = useDataProvider()
|
|
const refresh = useRefresh()
|
|
|
|
const refreshRecord = useCallback(() => {
|
|
// A playlistTrack id is a position, not a stable key: loving a song can drop it out of
|
|
// a smart playlist, and that position then holds a different track. Refetching the row
|
|
// by id would write the neighbour's data under this row, so reload the list instead.
|
|
const isPlaylistTrack = !!record.mediaFileId
|
|
const target = isPlaylistTrack
|
|
? { resource: 'song', params: { id: record.mediaFileId } }
|
|
: { resource, params: { id: record.id } }
|
|
|
|
dataProvider
|
|
.getOne(target.resource, target.params)
|
|
.catch((e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log('Error encountered: ' + e)
|
|
})
|
|
.finally(() => {
|
|
if (isPlaylistTrack) {
|
|
refresh()
|
|
}
|
|
if (mountedRef.current) {
|
|
setLoading(false)
|
|
}
|
|
})
|
|
}, [dataProvider, record.mediaFileId, record.id, refresh, resource])
|
|
|
|
const toggleLove = () => {
|
|
const toggle = record.starred ? subsonic.unstar : subsonic.star
|
|
const id = record.mediaFileId || record.id
|
|
|
|
setLoading(true)
|
|
toggle(id)
|
|
.then(refreshRecord)
|
|
.catch((e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log('Error toggling love: ', e)
|
|
notify('ra.page.error', 'warning')
|
|
if (mountedRef.current) {
|
|
setLoading(false)
|
|
}
|
|
})
|
|
}
|
|
|
|
return [toggleLove, loading]
|
|
}
|