diff --git a/CHANGELOG.md b/CHANGELOG.md
index 835747a7..87c3a019 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -153,6 +153,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
+### Fullscreen player — corner clock follows Clock format setting
+
+**By [@cucadmuh](https://github.com/cucadmuh), reported by zunoz on Discord, PR [#1025](https://github.com/Psychotoxical/psysonic/pull/1025)**
+
+* The wall clock in the fullscreen player now honours **Settings → System → Clock format** (24-hour vs 12-hour), matching the queue ETA and sleep-timer preview instead of always showing AM/PM.
+
+
+
## [1.47.0]
> **🙏 Thank you to our amazing Discord community.** This release would not have been possible without your tireless support, quality checks, bug reports and all-round collaboration. Every report, every repro and every bit of feedback shaped what shipped here — thank you. Come join us: [discord.gg/AMnDRErm4u](https://discord.gg/AMnDRErm4u)
diff --git a/src/components/fullscreenPlayer/FsClock.test.tsx b/src/components/fullscreenPlayer/FsClock.test.tsx
new file mode 100644
index 00000000..4c63ba1b
--- /dev/null
+++ b/src/components/fullscreenPlayer/FsClock.test.tsx
@@ -0,0 +1,31 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import { screen } from '@testing-library/react';
+import { renderWithProviders } from '../../test/helpers/renderWithProviders';
+import { resetAuthStore } from '../../test/helpers/storeReset';
+import { useAuthStore } from '../../store/authStore';
+import { FsClock } from './FsClock';
+
+describe('FsClock', () => {
+ beforeEach(() => {
+ vi.useFakeTimers();
+ vi.setSystemTime(new Date(2026, 0, 1, 21, 59, 0));
+ resetAuthStore();
+ });
+
+ afterEach(() => {
+ vi.useRealTimers();
+ });
+
+ it('uses the 24-hour clock format from Settings → System', () => {
+ useAuthStore.setState({ clockFormat: '24h' });
+ renderWithProviders();
+ expect(screen.getByText('21:59')).toBeInTheDocument();
+ expect(screen.queryByText(/AM|PM/i)).toBeNull();
+ });
+
+ it('uses the 12-hour clock format when selected', () => {
+ useAuthStore.setState({ clockFormat: '12h' });
+ renderWithProviders();
+ expect(screen.getByText('09:59 PM')).toBeInTheDocument();
+ });
+});
diff --git a/src/components/fullscreenPlayer/FsClock.tsx b/src/components/fullscreenPlayer/FsClock.tsx
index 5c3d3e4c..190dce64 100644
--- a/src/components/fullscreenPlayer/FsClock.tsx
+++ b/src/components/fullscreenPlayer/FsClock.tsx
@@ -1,8 +1,7 @@
import { memo, useEffect, useState } from 'react';
-
-function formatClock(): string {
- return new Date().toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
-}
+import { useTranslation } from 'react-i18next';
+import { useAuthStore } from '../../store/authStore';
+import { formatClockTime } from '../../utils/format/formatClockTime';
/**
* Standalone wall-clock for the fullscreen player. Owns its own state so the
@@ -10,11 +9,19 @@ function formatClock(): string {
* the minute rollover) and pauses while the window/tab is hidden.
*/
export const FsClock = memo(function FsClock() {
- const [time, setTime] = useState(formatClock);
+ const clockFormat = useAuthStore(s => s.clockFormat);
+ const { i18n } = useTranslation();
+
+ const formatNow = () => formatClockTime(Date.now(), clockFormat, i18n.language);
+ const [time, setTime] = useState(formatNow);
+
+ useEffect(() => {
+ setTime(formatNow());
+ }, [clockFormat, i18n.language]);
useEffect(() => {
let id: number | undefined;
- const tick = () => setTime(formatClock());
+ const tick = () => setTime(formatClockTime(Date.now(), clockFormat, i18n.language));
const sync = () => {
if (document.hidden) {
if (id !== undefined) { clearInterval(id); id = undefined; }
@@ -29,7 +36,7 @@ export const FsClock = memo(function FsClock() {
if (id !== undefined) clearInterval(id);
document.removeEventListener('visibilitychange', sync);
};
- }, []);
+ }, [clockFormat, i18n.language]);
return {time};
});