mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
fix(fullscreen): respect Settings clock format on wall clock (#1025)
* fix(fullscreen): respect Settings clock format on wall clock The fullscreen player corner clock always used the browser locale default (12-hour). Route it through formatClockTime and authStore.clockFormat so 24-hour matches queue ETA and sleep-timer preview. * docs(changelog): fullscreen clock format fix (PR #1025)
This commit is contained in:
@@ -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]
|
## [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)
|
> **🙏 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)
|
||||||
|
|||||||
@@ -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(<FsClock />);
|
||||||
|
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(<FsClock />);
|
||||||
|
expect(screen.getByText('09:59 PM')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
import { memo, useEffect, useState } from 'react';
|
import { memo, useEffect, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
function formatClock(): string {
|
import { useAuthStore } from '../../store/authStore';
|
||||||
return new Date().toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
|
import { formatClockTime } from '../../utils/format/formatClockTime';
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standalone wall-clock for the fullscreen player. Owns its own state so the
|
* 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.
|
* the minute rollover) and pauses while the window/tab is hidden.
|
||||||
*/
|
*/
|
||||||
export const FsClock = memo(function FsClock() {
|
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(() => {
|
useEffect(() => {
|
||||||
let id: number | undefined;
|
let id: number | undefined;
|
||||||
const tick = () => setTime(formatClock());
|
const tick = () => setTime(formatClockTime(Date.now(), clockFormat, i18n.language));
|
||||||
const sync = () => {
|
const sync = () => {
|
||||||
if (document.hidden) {
|
if (document.hidden) {
|
||||||
if (id !== undefined) { clearInterval(id); id = undefined; }
|
if (id !== undefined) { clearInterval(id); id = undefined; }
|
||||||
@@ -29,7 +36,7 @@ export const FsClock = memo(function FsClock() {
|
|||||||
if (id !== undefined) clearInterval(id);
|
if (id !== undefined) clearInterval(id);
|
||||||
document.removeEventListener('visibilitychange', sync);
|
document.removeEventListener('visibilitychange', sync);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [clockFormat, i18n.language]);
|
||||||
|
|
||||||
return <span className="fsp-clock">{time}</span>;
|
return <span className="fsp-clock">{time}</span>;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user