From f9c29df4156cf7b401ff2138fdd0c2f5cb35b767 Mon Sep 17 00:00:00 2001 From: librelad Date: Sat, 18 Jul 2026 22:03:36 +0100 Subject: [PATCH] fix(overview): path deep-link for an expanded Updates row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The expanded-row deep-link pushed /overview/?app= — wrong prefix and a ?query the SPA's path-based router drops on a cold load, so the row never reopened from a shared URL. Switch to /apps/overview/updates/, matching the Migrate/Backups sub-tab path pattern, and parse the app from that path segment in _honorAppDeepLink so the row expands on cold load too. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../apps/overview/js/overview-manager.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js index 168bcbc..60fb43b 100644 --- a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js +++ b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js @@ -186,7 +186,7 @@ class OverviewManager { case 'updates': { // Preserve which rows are expanded across a rebuild — a background // task-refresh repaints the whole table, so restore ALL open rows, not - // just the single ?app= deep-link. + // just the single /apps/overview/updates/ path deep-link. const open = Array.from(document.querySelectorAll('#overview-view .ov-row-details:not([hidden])')) .map((d) => d.id.replace(/^ov-detail-/, '')); const anyUpdate = !!(this.updater && this.updater.apps.some((a) => a.update_available)); @@ -278,10 +278,13 @@ class OverviewManager { } } - // Open the row named by ?app= on load / repaint — makes an expanded row - // a shareable URL, mirroring the Tasks page's ?task= deep-link. + // Open the row named by the /apps/overview/updates/ path segment on + // load / repaint — makes an expanded row a shareable URL, mirroring the + // Migrate/Backups sub-tab path deep-links (and unlike a ?query it survives + // the SPA's path-based router on a cold load). _honorAppDeepLink() { - const app = new URLSearchParams(window.location.search).get('app'); + const seg = window.location.pathname.replace(/^\/apps\/overview\/updates\/?/, '').split('/')[0]; + const app = seg ? decodeURIComponent(seg) : ''; if (!app) return; const details = document.getElementById(`ov-detail-${app}`); if (details && details.hidden) this._openDetail(app); @@ -564,13 +567,13 @@ class OverviewManager { if (!app) return; const details = document.getElementById(`ov-detail-${app}`); if (!details) return; - const base = `/overview/${this.current || 'updates'}`; + const base = `/apps/overview/${this.current || 'updates'}`; if (!details.hidden) { this._closeDetail(app); this._pushUrl(base, true); } else { this._openDetail(app); - this._pushUrl(`${base}?app=${encodeURIComponent(app)}`, true); + this._pushUrl(`${base}/${encodeURIComponent(app)}`, true); } } @@ -581,7 +584,7 @@ class OverviewManager { // Fill (lazily) + show a row's detail body. URL/history is handled by the // caller, so this is safe to call when restoring multiple rows after a - // rebuild without each one clobbering the ?app= deep-link. + // rebuild without each one clobbering the /apps/overview/updates/ deep-link. _openDetail(app) { const details = document.getElementById(`ov-detail-${app}`); if (!details) return;