From 48da88c12d04816f929ccddf827aecc851389d8f Mon Sep 17 00:00:00 2001 From: Julien Maille Date: Sun, 18 Jan 2026 23:25:23 +0100 Subject: [PATCH] feat: implement transient scroll restoration and disable Lenis --- js/app.js | 41 +++++++++++++++++++++++++++++++++++++++-- js/router.js | 20 ++++++++++---------- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/js/app.js b/js/app.js index f2af500..385f4d7 100644 --- a/js/app.js +++ b/js/app.js @@ -955,8 +955,45 @@ document.addEventListener('DOMContentLoaded', async () => { document.querySelector('.play-pause-btn').innerHTML = SVG_PLAY; const router = createRouter(ui); - router(); - window.addEventListener('hashchange', router); + + // Session-based scroll positions (transient, cleared on refresh) + const scrollPositions = new Map(); + + const handleRouter = async (e) => { + // Save scroll position for the previous page if available + if (e && e.oldURL) { + try { + const url = new URL(e.oldURL); + const oldHash = url.hash || '#home'; + const content = document.querySelector('.main-content'); + if (content) { + scrollPositions.set(oldHash, content.scrollTop); + } + } catch { + // Ignore URL parsing errors + } + } + + // Render the new page + await router(); + + // Restore scroll position for the new page + const newHash = window.location.hash || '#home'; + const content = document.querySelector('.main-content'); + if (content) { + const savedScroll = scrollPositions.get(newHash); + if (savedScroll !== undefined) { + // Small timeout to ensure DOM layout is stable after render + setTimeout(() => { + content.scrollTop = savedScroll; + }, 0); + } + } + }; + + // Initial load + await handleRouter(null); + window.addEventListener('hashchange', handleRouter); // Simple Navigation History const navStack = [window.location.hash]; diff --git a/js/router.js b/js/router.js index d028b0d..9fcfbca 100644 --- a/js/router.js +++ b/js/router.js @@ -2,37 +2,37 @@ import { getTrackArtists } from './utils.js'; export function createRouter(ui) { - const router = () => { + const router = async () => { const path = window.location.hash.substring(1) || 'home'; const [page, param] = path.split('/'); switch (page) { case 'search': - ui.renderSearchPage(decodeURIComponent(param)); + await ui.renderSearchPage(decodeURIComponent(param)); break; case 'album': - ui.renderAlbumPage(param); + await ui.renderAlbumPage(param); break; case 'artist': - ui.renderArtistPage(param); + await ui.renderArtistPage(param); break; case 'playlist': - ui.renderPlaylistPage(param, 'api'); + await ui.renderPlaylistPage(param, 'api'); break; case 'userplaylist': - ui.renderPlaylistPage(param, 'user'); + await ui.renderPlaylistPage(param, 'user'); break; case 'mix': - ui.renderMixPage(param); + await ui.renderMixPage(param); break; case 'library': - ui.renderLibraryPage(); + await ui.renderLibraryPage(); break; case 'recent': - ui.renderRecentPage(); + await ui.renderRecentPage(); break; case 'home': - ui.renderHomePage(); + await ui.renderHomePage(); break; default: ui.showPage(page);