fix(ui): honor EnableCoverAnimation for theme cover animations (#6234)

* fix: honor cover animation setting in Squiddies Glass

Fixes #5170

* fix(ui): move cover animation check into AlbumDetails

Apply a noCoverAnimation class from AlbumDetails when
enableCoverAnimation is off, so every theme gets the fix. Drop the
Squiddies Glass theme changes and its test, and cover the class in
AlbumDetails.test.jsx.

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
This commit is contained in:
Matt Van Horn 2026-09-28 15:06:44 -07:00 • committed by GitHub
commit a62d1629f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 79 additions and 2 deletions

View file

@ -16,6 +16,7 @@ import {
useRecordContext,
useTranslate,
} from 'react-admin'
import clsx from 'clsx'
import Lightbox from 'react-image-lightbox'
import config from '../config'
import 'react-image-lightbox/style.css'
@ -79,6 +80,9 @@ const useStyles = makeStyles(
alignItems: 'center',
justifyContent: 'center',
},
noCoverAnimation: {
'&, &::before, &::after': { animation: 'none' },
},
cover: {
objectFit: 'contain',
cursor: 'pointer',
@ -250,7 +254,12 @@ const AlbumDetails = (props) => {
return (
<Card className={classes.root}>
<div className={classes.cardContents}>
<div className={classes.coverParent}>
<div
className={clsx(
classes.coverParent,
!config.enableCoverAnimation && classes.noCoverAnimation,
)}
>
<Artwork
record={record}
fit="contain"

View file

@ -3,7 +3,29 @@ import { describe, test, expect, beforeEach, afterEach } from 'vitest'
import { render } from '@testing-library/react'
import { RecordContextProvider } from 'react-admin'
import { useMediaQuery } from '@material-ui/core'
import { Details } from './AlbumDetails'
import { createTheme, ThemeProvider } from '@material-ui/core/styles'
import config from '../config'
import AlbumDetails, { Details } from './AlbumDetails'
vi.mock('../subsonic', () => ({
default: {
getAlbumInfo: () =>
Promise.resolve({
json: { 'subsonic-response': { status: 'ok', albumInfo: {} } },
}),
getCoverArtUrl: () => '',
},
}))
vi.mock('react-admin', async () => {
const actual = await vi.importActual('react-admin')
return {
...actual,
useDataProvider: () => ({ getOne: vi.fn() }),
useNotify: () => vi.fn(),
useRefresh: () => vi.fn(),
}
})
// Mock useMediaQuery
vi.mock('@material-ui/core', async () => {
@ -343,3 +365,49 @@ describe('Details component', () => {
})
})
})
describe('AlbumDetails cover animation', () => {
const albumRecord = {
id: '123',
name: 'Test Album',
songCount: 12,
duration: 3600,
size: 102400,
}
const originalEnableCoverAnimation = config.enableCoverAnimation
beforeEach(() => {
vi.mocked(useMediaQuery).mockReturnValue(false)
})
afterEach(() => {
config.enableCoverAnimation = originalEnableCoverAnimation
})
const renderAlbum = () =>
render(
<ThemeProvider theme={createTheme()}>
<RecordContextProvider value={albumRecord}>
<AlbumDetails />
</RecordContextProvider>
</ThemeProvider>,
)
test('applies noCoverAnimation when enableCoverAnimation is false', () => {
config.enableCoverAnimation = false
const { container } = renderAlbum()
const cover = container.querySelector('[class*="coverParent"]')
expect(cover).not.toBeNull()
expect(cover.className).toMatch(/noCoverAnimation/)
})
test('omits noCoverAnimation when enableCoverAnimation is true', () => {
config.enableCoverAnimation = true
const { container } = renderAlbum()
const cover = container.querySelector('[class*="coverParent"]')
expect(cover).not.toBeNull()
expect(cover.className).not.toMatch(/noCoverAnimation/)
})
})