From bd742c958cfa5051fa7f878ce601b662266760f2 Mon Sep 17 00:00:00 2001 From: Frank Stellmacher <171614930+Psychotoxical@users.noreply.github.com> Date: Fri, 22 May 2026 01:18:29 +0200 Subject: [PATCH] fix(playlist): sorting a column no longer snaps the viewport (#840) (#848) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(playlist): sorting a column no longer snaps the viewport (#840) Sorting flipped `isFiltered` (which means displayedSongs !== songs, so it also goes true once a sort is active), and the scroll-to-list effect fired on `[id, isFiltered]` → the viewport snapped down to the list. Drive that effect from a dedicated `hasActiveFilter` (filter text only), so sorting applies in place; filter and playlist-switch scrolling are unchanged. * docs(changelog): playlist sort viewport fix (#848) --- CHANGELOG.md | 8 ++++++++ src/components/playlist/PlaylistTracklist.tsx | 8 ++++++-- src/pages/PlaylistDetail.tsx | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdf59871..57fe01a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -127,6 +127,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 +### Playlists — column sorting keeps the viewport in place + +**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#848](https://github.com/Psychotoxical/psysonic/pull/848)** + +* Sorting a playlist column no longer snaps the viewport down to the list when scrolled to the top. + + + ## [1.46.0] - 2026-05-18 > **🙏 Special thanks to [@zz5zz](https://github.com/zz5zz)** for his tireless quirk-spotting and bug reports on the [Psysonic Discord](https://discord.gg/AMnDRErm4u) — several of the polish fixes in this release landed directly off the back of his messages. diff --git a/src/components/playlist/PlaylistTracklist.tsx b/src/components/playlist/PlaylistTracklist.tsx index 558ce166..c544a11c 100644 --- a/src/components/playlist/PlaylistTracklist.tsx +++ b/src/components/playlist/PlaylistTracklist.tsx @@ -41,6 +41,10 @@ interface Props { displayedSongs: SubsonicSong[]; displayedTracks: Track[]; isFiltered: boolean; + /** True only while a filter text is active — distinct from `isFiltered`, + * which also goes true while sorting (displayedSongs !== songs). Drives the + * scroll-to-list effect so sorting doesn't snap the viewport (issue #840). */ + hasActiveFilter: boolean; id: string | undefined; // Sort @@ -82,7 +86,7 @@ interface Props { export default function PlaylistTracklist({ allColumns, visibleCols, gridStyle, colVisible, toggleColumn, resetColumns, pickerOpen, setPickerOpen, pickerRef, startResize, tracklistRef, - songs, displayedSongs, displayedTracks, isFiltered, id, + songs, displayedSongs, displayedTracks, isFiltered, hasActiveFilter, id, sortKey, setSortKey, sortDir, setSortDir, sortClickCount, setSortClickCount, selectedIds, setSelectedIds, allSelected, toggleAll, toggleSelect, showBulkPlPicker, setShowBulkPlPicker, bulkRemove, @@ -190,7 +194,7 @@ export default function PlaylistTracklist({ const sc = document.getElementById(APP_MAIN_SCROLL_VIEWPORT_ID); if (sc) sc.scrollTop = scrollMargin; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [id, isFiltered]); + }, [id, hasActiveFilter]); const autoScrollRef = useRef(0); const pointerYRef = useRef(0); diff --git a/src/pages/PlaylistDetail.tsx b/src/pages/PlaylistDetail.tsx index e48027e2..97c6db2f 100644 --- a/src/pages/PlaylistDetail.tsx +++ b/src/pages/PlaylistDetail.tsx @@ -349,6 +349,7 @@ export default function PlaylistDetail() { displayedSongs={displayedSongs} displayedTracks={displayedTracks} isFiltered={isFiltered} + hasActiveFilter={filterText.trim().length > 0} id={id} sortKey={sortKey} setSortKey={setSortKey}