diff --git a/CHANGELOG.md b/CHANGELOG.md index a5a182e9..d6afd83d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,11 +47,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Settings — consistent grouped layout -**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1126](https://github.com/Psychotoxical/psysonic/pull/1126)** +**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1126](https://github.com/Psychotoxical/psysonic/pull/1126) and PR [#1130](https://github.com/Psychotoxical/psysonic/pull/1130)** * The settings tabs now group related controls into clearly bordered, labelled panels for a more consistent, easier-to-scan layout — across Appearance, System, Audio, Storage, Library, Integrations, Music Network, Lyrics, Personalisation, Input and Themes. Standalone toggles are left as they were, and a few duplicated section titles are gone. * The **Lucky Mix menu** toggle moved from the Library tab to the sidebar customizer, alongside the other navigation toggles. * The **Native Hi-Res Playback** description now explains what turning it on actually does — play each track at its original sample rate, matching the audio device to the file, instead of resampling everything to 44.1 kHz. The old wording described the off state and read as if the option forced 44.1 kHz. +* **Settings → Audio**: **Normalization** and **Track transitions** are now their own top-level categories (directly under Audio Output Device) instead of being grouped together inside one *Playback* section. +* **Settings → Personalisation** gains a **Queue Settings** category that brings the queue display mode, the queue toolbar customizer, and the **Preserve "Play Next" order** toggle (moved here from Audio) together in one place. +* On macOS, the **Audio Output Device** category is now hidden rather than showing a notice — playback there always follows the system output device. ## Fixed diff --git a/WHATS_NEW.md b/WHATS_NEW.md index 6778a9b9..3d87cbac 100644 --- a/WHATS_NEW.md +++ b/WHATS_NEW.md @@ -28,6 +28,7 @@ Within each section, order by **user impact** (most noticeable first) — not PR ### Settings — tidier and easier to scan - Settings are grouped into clear, labelled panels so related options sit together — less hunting around. The **Native Hi-Res Playback** option now explains in plain language what it actually does. +- **Normalization** and **Track transitions** are now their own sections under **Settings → Audio**, and the queue options (display mode, toolbar, and Play-Next order) are gathered into one **Queue Settings** group under **Personalisation**. ## Fixed diff --git a/src/components/settings/AudioTab.tsx b/src/components/settings/AudioTab.tsx index 8c0e50d5..c8d360f8 100644 --- a/src/components/settings/AudioTab.tsx +++ b/src/components/settings/AudioTab.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Music2, Sliders, Waves } from 'lucide-react'; +import { Blend, Gauge, Sliders, Volume2, Waves } from 'lucide-react'; import { useAuthStore } from '../../store/authStore'; import Equalizer from '../Equalizer'; import SettingsSubSection from '../SettingsSubSection'; @@ -8,11 +8,11 @@ import { SettingsGroup } from './SettingsGroup'; import { SettingsToggle } from './SettingsToggle'; import { effectiveLoudnessPreAnalysisAttenuationDb } from '../../utils/audio/loudnessPreAnalysisSlider'; import { useAudioDevicesProbe } from '../../hooks/useAudioDevicesProbe'; +import { IS_MACOS } from '../../utils/platform'; import { AudioOutputDeviceSection } from './audio/AudioOutputDeviceSection'; import { NormalizationBlock } from './audio/NormalizationBlock'; -import { Gauge } from 'lucide-react'; -import { PlaybackBehaviorBlock } from './audio/PlaybackBehaviorBlock'; import { PlaybackRateBlock } from './audio/PlaybackRateBlock'; +import { TrackTransitionsBlock } from './audio/TrackTransitionsBlock'; import { TrackPreviewsSection } from './audio/TrackPreviewsSection'; export function AudioTab() { @@ -37,15 +37,41 @@ export function AudioTab() { return ( <> - + {/* Output-device picker is hidden on macOS — the stream is pinned to the + system default there, so the whole category is gated out. */} + {!IS_MACOS && ( + + )} + + {/* Normalization — loudness levelling (own category) */} + } + > +
+ +
+
+ + {/* Track transitions — crossfade / gapless / AutoDJ (own category) */} + } + > +
+ +
+
{/* Native Hi-Res Playback */} - {/* Replay Gain + Crossfade + Gapless */} - } - > -
- - -
-
- ); diff --git a/src/components/settings/PersonalisationTab.tsx b/src/components/settings/PersonalisationTab.tsx index e06658ec..76750f54 100644 --- a/src/components/settings/PersonalisationTab.tsx +++ b/src/components/settings/PersonalisationTab.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { Disc3, LayoutGrid, ListMusic, ListOrdered, ListTodo, PanelLeft, RotateCcw, Users } from 'lucide-react'; +import { Disc3, LayoutGrid, ListOrdered, ListTodo, PanelLeft, RotateCcw, Users } from 'lucide-react'; import { useArtistLayoutStore } from '../../store/artistLayoutStore'; import { useAuthStore } from '../../store/authStore'; import { useHomeStore } from '../../store/homeStore'; @@ -21,6 +21,9 @@ export function PersonalisationTab() { const { t } = useTranslation(); const queueDisplayMode = useAuthStore(s => s.queueDisplayMode); const setQueueDisplayMode = useAuthStore(s => s.setQueueDisplayMode); + const preservePlayNextOrder = useAuthStore(s => s.preservePlayNextOrder); + const setPreservePlayNextOrder = useAuthStore(s => s.setPreservePlayNextOrder); + const advancedSettingsEnabled = useAuthStore(s => s.advancedSettingsEnabled); return ( <> } > - - - + + {/* Queue Settings — display mode, queue behaviour and (advanced) the + toolbar customizer, grouped under one category. */} } > -
- + <> + {/* Three mutually exclusive modes — exactly one is always active, so turning one on turns the others off; the active one cannot be switched off directly (ignore the uncheck). */} @@ -117,29 +120,37 @@ export function PersonalisationTab() { onChange={c => { if (c) setQueueDisplayMode('timeline'); }} /> -
-
- } - advanced - action={ - - } - > - - - + + + + + {advancedSettingsEnabled && ( + useQueueToolbarStore.getState().reset()} + data-tooltip={t('settings.queueToolbarReset')} + aria-label={t('settings.queueToolbarReset')} + > + + + } + > + + + )} + ) : ( -
+ // Reserve the same 16px icon column so the label lines up with the + // other rows; the 1px rule is centred within it. +
+
+
)} {label}