mirror of
https://github.com/navidrome/navidrome.git
synced 2026-03-04 06:35:52 +00:00
Introduced a new event, EVENT_STREAM_RECONNECTED, to track the last timestamp of stream reconnections. This change updates the activity reducer to handle the new event and modifies the NowPlayingPanel to refresh data based on server and stream status. Signed-off-by: Deluan <deluan@navidrome.org>
115 lines
3.3 KiB
JavaScript
115 lines
3.3 KiB
JavaScript
import { baseUrl } from './utils'
|
|
import throttle from 'lodash.throttle'
|
|
import { processEvent, serverDown, streamReconnected } from './actions'
|
|
import { REST_URL } from './consts'
|
|
import config from './config'
|
|
|
|
const newEventStream = async () => {
|
|
let url = baseUrl(`${REST_URL}/events`)
|
|
if (localStorage.getItem('token')) {
|
|
url = url + `?jwt=${localStorage.getItem('token')}`
|
|
}
|
|
return new EventSource(url)
|
|
}
|
|
|
|
let eventStream
|
|
let reconnectTimer
|
|
const RECONNECT_DELAY = 5000
|
|
|
|
const setupHandlers = (stream, dispatchFn) => {
|
|
stream.addEventListener('serverStart', eventHandler(dispatchFn))
|
|
stream.addEventListener('scanStatus', throttledEventHandler(dispatchFn))
|
|
stream.addEventListener('refreshResource', eventHandler(dispatchFn))
|
|
if (config.enableNowPlaying) {
|
|
stream.addEventListener('nowPlayingCount', eventHandler(dispatchFn))
|
|
}
|
|
stream.addEventListener('keepAlive', eventHandler(dispatchFn))
|
|
stream.onerror = (e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log('EventStream error', e)
|
|
dispatchFn(serverDown())
|
|
if (stream) stream.close()
|
|
scheduleReconnect(dispatchFn)
|
|
}
|
|
}
|
|
|
|
const scheduleReconnect = (dispatchFn) => {
|
|
if (!reconnectTimer) {
|
|
reconnectTimer = setTimeout(() => {
|
|
reconnectTimer = null
|
|
connect(dispatchFn)
|
|
}, RECONNECT_DELAY)
|
|
}
|
|
}
|
|
|
|
const connect = async (dispatchFn) => {
|
|
try {
|
|
const stream = await newEventStream()
|
|
eventStream = stream
|
|
setupHandlers(stream, dispatchFn)
|
|
// Dispatch reconnection event to refresh critical data
|
|
dispatchFn(streamReconnected())
|
|
return stream
|
|
} catch (e) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(`Error connecting to server:`, e)
|
|
scheduleReconnect(dispatchFn)
|
|
}
|
|
}
|
|
|
|
const eventHandler = (dispatchFn) => (event) => {
|
|
const data = JSON.parse(event.data)
|
|
if (event.type !== 'keepAlive') {
|
|
dispatchFn(processEvent(event.type, data))
|
|
}
|
|
}
|
|
|
|
const throttledEventHandler = (dispatchFn) =>
|
|
throttle(eventHandler(dispatchFn), 100, { trailing: true })
|
|
|
|
const startEventStreamLegacy = async (dispatchFn) => {
|
|
return newEventStream()
|
|
.then((newStream) => {
|
|
newStream.addEventListener('serverStart', eventHandler(dispatchFn))
|
|
newStream.addEventListener(
|
|
'scanStatus',
|
|
throttledEventHandler(dispatchFn),
|
|
)
|
|
newStream.addEventListener('refreshResource', eventHandler(dispatchFn))
|
|
if (config.enableNowPlaying) {
|
|
newStream.addEventListener('nowPlayingCount', eventHandler(dispatchFn))
|
|
}
|
|
newStream.addEventListener('keepAlive', eventHandler(dispatchFn))
|
|
newStream.onerror = (e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log('EventStream error', e)
|
|
dispatchFn(serverDown())
|
|
}
|
|
return newStream
|
|
})
|
|
.catch((e) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log(`Error connecting to server:`, e)
|
|
})
|
|
}
|
|
|
|
const startEventStreamNew = async (dispatchFn) => {
|
|
if (eventStream) {
|
|
eventStream.close()
|
|
eventStream = null
|
|
}
|
|
return connect(dispatchFn)
|
|
}
|
|
|
|
const startEventStream = async (dispatchFn) => {
|
|
if (!localStorage.getItem('is-authenticated')) {
|
|
return Promise.resolve()
|
|
}
|
|
if (config.devNewEventStream) {
|
|
return startEventStreamNew(dispatchFn)
|
|
}
|
|
return startEventStreamLegacy(dispatchFn)
|
|
}
|
|
|
|
export { startEventStream }
|