fix(ui): improve elapsed time handling during scans
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -1,12 +1,23 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState, useRef } from 'react'
|
||||||
import { useInterval } from '../common'
|
import { useInterval } from '../common'
|
||||||
|
|
||||||
export const useScanElapsedTime = (scanning, elapsedTime) => {
|
export const useScanElapsedTime = (scanning, elapsedTime) => {
|
||||||
const [elapsed, setElapsed] = useState(Number(elapsedTime) || 0)
|
const [elapsed, setElapsed] = useState(Number(elapsedTime) || 0)
|
||||||
|
const prevScanningRef = useRef(scanning)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setElapsed(Number(elapsedTime) || 0)
|
// Only update from server when scan starts or stops
|
||||||
}, [elapsedTime])
|
const prevScanning = prevScanningRef.current
|
||||||
|
if (!prevScanning && scanning) {
|
||||||
|
// Scan just started - initialize with server value
|
||||||
|
setElapsed(Number(elapsedTime) || 0)
|
||||||
|
} else if (prevScanning && !scanning) {
|
||||||
|
// Scan just finished - use final server value
|
||||||
|
setElapsed(Number(elapsedTime) || 0)
|
||||||
|
}
|
||||||
|
// Update ref for next comparison
|
||||||
|
prevScanningRef.current = scanning
|
||||||
|
}, [scanning, elapsedTime])
|
||||||
|
|
||||||
useInterval(() => setElapsed((prev) => prev + 1e9), scanning ? 1000 : null)
|
useInterval(() => setElapsed((prev) => prev + 1e9), scanning ? 1000 : null)
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,75 @@ describe('useScanElapsedTime', () => {
|
|||||||
|
|
||||||
expect(result.current).toBe(3e9)
|
expect(result.current).toBe(3e9)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('initializes with server value when scan starts', () => {
|
||||||
|
const { result, rerender } = renderHook(
|
||||||
|
({ scanning, elapsed }) => useScanElapsedTime(scanning, elapsed),
|
||||||
|
{
|
||||||
|
initialProps: { scanning: false, elapsed: 5e9 },
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Start scanning with a new elapsed time from server
|
||||||
|
rerender({ scanning: true, elapsed: 10e9 })
|
||||||
|
|
||||||
|
// Should use the server value when starting
|
||||||
|
expect(result.current).toBe(10e9)
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
vi.advanceTimersByTime(2000)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Should continue from server value
|
||||||
|
expect(result.current).toBe(12e9)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('ignores server updates during scanning', () => {
|
||||||
|
const { result, rerender } = renderHook(
|
||||||
|
({ scanning, elapsed }) => useScanElapsedTime(scanning, elapsed),
|
||||||
|
{
|
||||||
|
initialProps: { scanning: true, elapsed: 0 },
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
vi.advanceTimersByTime(3000)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.current).toBe(3e9)
|
||||||
|
|
||||||
|
// Server sends updated elapsed time during scan
|
||||||
|
rerender({ scanning: true, elapsed: 10e9 })
|
||||||
|
|
||||||
|
// Should ignore server update while scanning
|
||||||
|
expect(result.current).toBe(3e9)
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
vi.advanceTimersByTime(1000)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Should continue from local timer
|
||||||
|
expect(result.current).toBe(4e9)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('uses final server value when scan ends', () => {
|
||||||
|
const { result, rerender } = renderHook(
|
||||||
|
({ scanning, elapsed }) => useScanElapsedTime(scanning, elapsed),
|
||||||
|
{
|
||||||
|
initialProps: { scanning: true, elapsed: 0 },
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
vi.advanceTimersByTime(3000)
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.current).toBe(3e9)
|
||||||
|
|
||||||
|
// Scan ends with final server value
|
||||||
|
rerender({ scanning: false, elapsed: 5e9 })
|
||||||
|
|
||||||
|
// Should use the final server value
|
||||||
|
expect(result.current).toBe(5e9)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user