mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-18 07:30:29 +00:00
fix(ui): coalesce lyric refreshes with in-flight requests
Signed-off-by: ranokay <github@ranokay.com>
This commit is contained in:
parent
1d01a7f787
commit
1022ffb56a
@ -153,8 +153,13 @@ const useEnhancedLyrics = ({
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
if (!trackId || disabled || !requested) return
|
||||
// Coalesce with an unsettled request: its answer is at least as fresh as
|
||||
// one started now, and restarting it would strand slow responses behind
|
||||
// the poll interval.
|
||||
const entry = inFlight.get(cacheKey)
|
||||
if (entry && !entry.settled) return
|
||||
setRefreshToken((current) => current + 1)
|
||||
}, [disabled, requested, trackId])
|
||||
}, [cacheKey, disabled, requested, trackId])
|
||||
|
||||
useEffect(() => {
|
||||
if (!trackId || disabled || !requested) {
|
||||
|
||||
@ -344,6 +344,29 @@ describe('useEnhancedLyrics', () => {
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('coalesces a refresh with a request that is still in flight', async () => {
|
||||
const pending = createDeferred()
|
||||
subsonic.getLyricsBySongId.mockReturnValueOnce(pending.promise)
|
||||
|
||||
const { result } = renderLyrics({ trackId: 'song-coalesce' })
|
||||
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(1)
|
||||
|
||||
act(() => {
|
||||
result.current.refresh()
|
||||
})
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(1)
|
||||
|
||||
act(() => {
|
||||
pending.resolve(
|
||||
responseForEntries([sourceEntry('NetEase', 'NetEase line')]),
|
||||
)
|
||||
})
|
||||
|
||||
await expectLyric(result, 'NetEase line')
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('keeps current lyrics when a refresh fails', async () => {
|
||||
subsonic.getLyricsBySongId
|
||||
.mockResolvedValueOnce(
|
||||
|
||||
@ -195,29 +195,32 @@ describe('usePlayerLyrics', () => {
|
||||
vi.useFakeTimers()
|
||||
subsonic.getLyricsBySongId.mockResolvedValue(variantsResponse())
|
||||
|
||||
const flushMicrotasks = () =>
|
||||
act(async () => {
|
||||
await Promise.resolve()
|
||||
await Promise.resolve()
|
||||
})
|
||||
|
||||
const { result } = renderPlayerLyrics()
|
||||
act(() => result.current.toolbarLyricsProps.onToggleLyrics())
|
||||
await act(async () => {
|
||||
await Promise.resolve()
|
||||
})
|
||||
await flushMicrotasks()
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(1)
|
||||
|
||||
act(() => result.current.desktopLyricsProps.onSourceMenuOpenChange(true))
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(2)
|
||||
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(5_000)
|
||||
})
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(3)
|
||||
|
||||
for (let step = 0; step < 11; step += 1) {
|
||||
let expectedCalls = 2
|
||||
for (let step = 0; step < 12; step += 1) {
|
||||
await flushMicrotasks()
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(5_000)
|
||||
})
|
||||
expectedCalls += 1
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(expectedCalls)
|
||||
}
|
||||
expect(subsonic.getLyricsBySongId).toHaveBeenCalledTimes(14)
|
||||
|
||||
act(() => result.current.desktopLyricsProps.onSourceMenuOpenChange(false))
|
||||
await flushMicrotasks()
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(15_000)
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user