feat(ui): add EnableNowPlaying configuration (default true) (#4219)

* Add EnableNowPlaying config option

* Return 501 for disabled NowPlaying

* chore(tests): remove get_now_playing_route test

* Disable now playing events when disabled

* fix(tests): add mutex for thread-safe access to scrobble buffer

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan Quintão
2025-06-13 00:06:08 -04:00
committed by GitHub
parent fcba2ba902
commit 043f79d746
14 changed files with 139 additions and 11 deletions
+1
View File
@@ -29,6 +29,7 @@ const defaultConfig = {
listenBrainzEnabled: true,
enableExternalServices: true,
enableCoverAnimation: true,
enableNowPlaying: true,
devShowArtistPage: true,
devUIShowConfig: true,
enableReplayGain: true,
+4 -1
View File
@@ -2,6 +2,7 @@ import { baseUrl } from './utils'
import throttle from 'lodash.throttle'
import { processEvent, serverDown } from './actions'
import { REST_URL } from './consts'
import config from './config'
const newEventStream = async () => {
let url = baseUrl(`${REST_URL}/events`)
@@ -33,7 +34,9 @@ const startEventStream = async (dispatchFn) => {
throttledEventHandler(dispatchFn),
)
newStream.addEventListener('refreshResource', eventHandler(dispatchFn))
newStream.addEventListener('nowPlayingCount', eventHandler(dispatchFn))
if (config.enableNowPlaying) {
newStream.addEventListener('nowPlayingCount', eventHandler(dispatchFn))
}
newStream.addEventListener('keepAlive', eventHandler(dispatchFn))
newStream.onerror = (e) => {
// eslint-disable-next-line no-console
+3 -3
View File
@@ -120,9 +120,9 @@ const CustomUserMenu = ({ onClick, ...rest }) => {
return (
<>
{config.devActivityPanel && permissions === 'admin' && (
<NowPlayingPanel />
)}
{config.devActivityPanel &&
permissions === 'admin' &&
config.enableNowPlaying && <NowPlayingPanel />}
{config.devActivityPanel && permissions === 'admin' && <ActivityPanel />}
<UserMenu {...rest}>
<PersonalMenu sidebarIsOpen={true} onClick={onClick} />
+65
View File
@@ -0,0 +1,65 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import { describe, it, beforeEach, vi } from 'vitest'
import { Provider } from 'react-redux'
import { createStore, combineReducers } from 'redux'
import { activityReducer } from '../reducers'
import AppBar from './AppBar'
import config from '../config'
let store
vi.mock('react-admin', () => ({
AppBar: ({ userMenu }) => <div data-testid="appbar">{userMenu}</div>,
useTranslate: () => (x) => x,
usePermissions: () => ({ permissions: 'admin' }),
getResources: () => [],
}))
vi.mock('./NowPlayingPanel', () => ({
default: () => <div data-testid="now-playing-panel" />,
}))
vi.mock('./ActivityPanel', () => ({
default: () => <div data-testid="activity-panel" />,
}))
vi.mock('./PersonalMenu', () => ({
default: () => <div />,
}))
vi.mock('./UserMenu', () => ({
default: ({ children }) => <div>{children}</div>,
}))
vi.mock('../dialogs/Dialogs', () => ({
Dialogs: () => <div />,
}))
vi.mock('../dialogs', () => ({
AboutDialog: () => <div />,
}))
describe('<AppBar />', () => {
beforeEach(() => {
config.devActivityPanel = true
config.enableNowPlaying = true
store = createStore(combineReducers({ activity: activityReducer }), {
activity: { nowPlayingCount: 0 },
})
})
it('renders NowPlayingPanel when enabled', () => {
render(
<Provider store={store}>
<AppBar />
</Provider>,
)
expect(screen.getByTestId('now-playing-panel')).toBeInTheDocument()
})
it('hides NowPlayingPanel when disabled', () => {
config.enableNowPlaying = false
render(
<Provider store={store}>
<AppBar />
</Provider>,
)
expect(screen.queryByTestId('now-playing-panel')).toBeNull()
})
})