feat(05-03): implement visibility-aware polling for position/duration
- Add polling effect with 500ms visible, 2000ms hidden intervals - Fetch position and duration via JamTrackGetPositionMs/GetDurationMs - Parse string values to int before using - Conditional state updates (only when values change) - End-of-track handling (stop and reset when position >= duration) - Add formatTime utility for MM:SS display - Update render to show formatted time - Add visibilitychange listener for dynamic interval adjustment Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
217005c94b
commit
e5e0102921
|
|
@ -183,6 +183,73 @@ const JKSessionJamTrackPlayer = ({
|
|||
}
|
||||
}, [isOperating, jamClient, dispatch]);
|
||||
|
||||
// Helper: Format milliseconds to MM:SS
|
||||
const formatTime = (ms) => {
|
||||
if (!ms || isNaN(ms)) return '00:00';
|
||||
const totalSeconds = Math.floor(ms / 1000);
|
||||
const minutes = Math.floor(totalSeconds / 60);
|
||||
const seconds = totalSeconds % 60;
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
// Polling for position and duration
|
||||
useEffect(() => {
|
||||
if (!jamClient || !fqIdRef.current || !jamTrackState.isPlaying) return;
|
||||
|
||||
// Check if tab is visible
|
||||
const isVisible = document.visibilityState === 'visible';
|
||||
const pollInterval = isVisible ? 500 : 2000;
|
||||
|
||||
const intervalId = setInterval(async () => {
|
||||
try {
|
||||
// Fetch position and duration
|
||||
const positionStr = await jamClient.JamTrackGetPositionMs(fqIdRef.current);
|
||||
const durationStr = await jamClient.JamTrackGetDurationMs(fqIdRef.current);
|
||||
|
||||
const position = parseInt(positionStr, 10);
|
||||
const duration = parseInt(durationStr, 10);
|
||||
|
||||
// Conditional update: only update if values changed
|
||||
if (
|
||||
position !== jamTrackState.currentPositionMs ||
|
||||
duration !== jamTrackState.durationMs
|
||||
) {
|
||||
dispatch(setJamTrackState({
|
||||
currentPositionMs: position,
|
||||
durationMs: duration,
|
||||
lastUpdate: Date.now()
|
||||
}));
|
||||
}
|
||||
|
||||
// End-of-track handling
|
||||
if (duration > 0 && position >= duration) {
|
||||
await jamClient.JamTrackStop(fqIdRef.current);
|
||||
dispatch(setJamTrackState({
|
||||
isPlaying: false,
|
||||
isPaused: false,
|
||||
currentPositionMs: 0
|
||||
}));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[JamTrack] Polling error:', err);
|
||||
// Don't setError - polling errors are non-critical
|
||||
}
|
||||
}, pollInterval);
|
||||
|
||||
return () => clearInterval(intervalId);
|
||||
}, [jamClient, jamTrackState.isPlaying, jamTrackState.currentPositionMs, jamTrackState.durationMs, dispatch]);
|
||||
|
||||
// Listen for visibility changes to recreate interval
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = () => {
|
||||
// Trigger polling effect to restart with new interval
|
||||
// This is handled by the dependency array
|
||||
};
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
}, []);
|
||||
|
||||
if (!isOpen && !isPopup) return null;
|
||||
|
||||
return (
|
||||
|
|
@ -213,7 +280,9 @@ const JKSessionJamTrackPlayer = ({
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<p>Position: {jamTrackState.currentPositionMs}ms / Duration: {jamTrackState.durationMs}ms</p>
|
||||
<p>
|
||||
{formatTime(jamTrackState.currentPositionMs)} / {formatTime(jamTrackState.durationMs)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue