diff --git a/server/events/events.go b/server/events/events.go index 00d991e6b..fb9d6ad71 100644 --- a/server/events/events.go +++ b/server/events/events.go @@ -40,6 +40,7 @@ type KeepAlive struct { type ServerStart struct { baseEvent StartTime time.Time `json:"startTime"` + Version string `json:"version"` } const Any = "*" diff --git a/server/events/sse.go b/server/events/sse.go index 4a4887ddf..a9f808b0b 100644 --- a/server/events/sse.go +++ b/server/events/sse.go @@ -208,7 +208,7 @@ func (b *broker) listen() { log.Debug("Client added to event broker", "numClients", len(clients), "newClient", c.String()) // Send a serverStart event to new client - c.diode.put(b.prepareMessage(&ServerStart{StartTime: consts.ServerStart})) + c.diode.put(b.prepareMessage(&ServerStart{StartTime: consts.ServerStart, Version: consts.Version()})) case c := <-b.unsubscribing: // A client has detached and we want to diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 41aedffae..f1d67903a 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -278,7 +278,8 @@ "data_provider_error": "dataProvider error. Check the console for details.", "i18n_error": "Cannot load the translations for the specified language", "canceled": "Action cancelled", - "logged_out": "Your session has ended, please reconnect." + "logged_out": "Your session has ended, please reconnect.", + "new_version": "New version available! Please refresh this window." }, "toggleFieldsMenu": { "columnsToDisplay": "Columns To Display", diff --git a/ui/src/layout/ActivityPanel.js b/ui/src/layout/ActivityPanel.js index 1c937a60e..6b67e95a7 100644 --- a/ui/src/layout/ActivityPanel.js +++ b/ui/src/layout/ActivityPanel.js @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useTranslate } from 'react-admin' +import { useNotify, useTranslate } from 'react-admin' import { Popover, Badge, @@ -22,6 +22,7 @@ import subsonic from '../subsonic' import { scanStatusUpdate } from '../actions' import { useInterval } from '../common' import { formatDuration } from '../utils' +import config from '../config' const useStyles = makeStyles((theme) => ({ wrapper: { @@ -58,9 +59,10 @@ const Uptime = () => { const ActivityPanel = () => { const serverStart = useSelector((state) => state.activity.serverStart) - const up = serverStart && serverStart.startTime + const up = serverStart.startTime const classes = useStyles({ up }) const translate = useTranslate() + const notify = useNotify() const [anchorEl, setAnchorEl] = useState(null) const open = Boolean(anchorEl) const dispatch = useDispatch() @@ -82,6 +84,12 @@ const ActivityPanel = () => { }) }, [dispatch]) + useEffect(() => { + if (serverStart.version !== config.version) { + notify('ra.notification.new_version', 'info', {}, false, 604800000 * 50) + } + }, [serverStart, notify]) + return (