diff --git a/CHANGELOG.md b/CHANGELOG.md index fa3326b3..03b0048d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -321,6 +321,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Connecting a scrobble service could fail with only "Network error — check your connection or URL", which covers everything from a DNS failure to a blocked host, an interrupted TLS handshake or a rejected request. The underlying error is now shown alongside it, so a failing connect can be told apart from a reachability problem on your machine or network. +### Windows — oversized Discord banner icon + +**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1289](https://github.com/Psychotoxical/psysonic/pull/1289)** + +* The Discord community banner rendered its icon at an enormous size on Windows, pushing the message out of the bar. The icon now has a fixed size on every platform. + ## [1.49.0] - 2026-06-29 diff --git a/src/features/discordBanner/DiscordBanner.test.tsx b/src/features/discordBanner/DiscordBanner.test.tsx new file mode 100644 index 00000000..da0b5625 --- /dev/null +++ b/src/features/discordBanner/DiscordBanner.test.tsx @@ -0,0 +1,40 @@ +// The banner icon shipped with a `viewBox` but no width/height and no CSS rule +// for its class, so it had no intrinsic size at all. WebKitGTK happened to +// render it small; Chromium (WebView2, i.e. Windows) fell back to the 300x150 +// default replaced-element size and the icon swallowed the bar. Pin the explicit +// dimensions — CSS alone cannot be asserted here, and the attributes are what +// make the icon correct even before the stylesheet applies. + +import { describe, expect, it, beforeEach, afterEach } from 'vitest'; +import { render } from '@testing-library/react'; +import DiscordBanner from './DiscordBanner'; +import { useAuthStore } from '@/store/authStore'; +import { resetAuthStore } from '@/test/helpers/storeReset'; + +const THRESHOLD_MS = 20 * 60 * 60 * 1000; + +describe('DiscordBanner', () => { + beforeEach(() => { + resetAuthStore(); + useAuthStore.setState({ discordBannerAccumulatedUsageMs: THRESHOLD_MS }); + }); + afterEach(resetAuthStore); + + it('sizes its icon explicitly instead of leaving it intrinsic', () => { + const { container } = render(); + const icon = container.querySelector('.discord-banner-icon'); + + expect(icon).not.toBeNull(); + expect(icon?.getAttribute('width')).toBe('18'); + expect(icon?.getAttribute('height')).toBe('18'); + }); + + it('keeps the icon inside the banner row next to the message and join button', () => { + const { container } = render(); + const left = container.querySelector('.discord-banner-left'); + + expect(left?.querySelector('.discord-banner-icon')).not.toBeNull(); + expect(left?.querySelector('.discord-banner-text')).not.toBeNull(); + expect(left?.querySelector('.discord-banner-join')).not.toBeNull(); + }); +}); diff --git a/src/features/discordBanner/DiscordBanner.tsx b/src/features/discordBanner/DiscordBanner.tsx index 431736e0..88bf262b 100644 --- a/src/features/discordBanner/DiscordBanner.tsx +++ b/src/features/discordBanner/DiscordBanner.tsx @@ -19,7 +19,17 @@ export default function DiscordBanner() { return (
- {t('discordBanner.message')} diff --git a/src/styles/layout/discord-banner.css b/src/styles/layout/discord-banner.css index b96e028f..e746f6ff 100644 --- a/src/styles/layout/discord-banner.css +++ b/src/styles/layout/discord-banner.css @@ -21,6 +21,12 @@ min-width: 0; } +.discord-banner-icon { + width: 18px; + height: 18px; + flex-shrink: 0; +} + .discord-banner-text { white-space: nowrap; overflow: hidden;