From 0d5ae61e32a1dc2c4f1da29cfcde2f8ab7dc45e5 Mon Sep 17 00:00:00 2001 From: librelad Date: Thu, 18 Jun 2026 16:42:46 +0100 Subject: [PATCH] fix(app-config): restore config sub-tab on cold-load deep-link/refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /app//config/ URLs (e.g. .../config/ports) are generated by the app itself and shown in the address bar, but a refresh or deep-link always reset to the first config category. Cause: showAppDetail() rebuilt the URL via appPath(appName, targetTab) with NO sub argument and pushState'd it BEFORE renderAppDetail() read the sub back off the path — so the / segment was already gone and preferredCategory stayed null. Preserve the sub when the URL already points at this app's config (matched by appPartsFromPath().app === appName), so cold-load/refresh lands on the encoded sub-tab. Cross-app switches still start at the first category. The sibling showAppDetailWithConfig() (the grid 'manage' button) is intentionally left to land on the first category. Co-Authored-By: Claude Opus 4.8 Signed-off-by: librelad --- .../components/apps/core/js/apps-manager.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/containers/libreportal/frontend/components/apps/core/js/apps-manager.js b/containers/libreportal/frontend/components/apps/core/js/apps-manager.js index 55fe288..41727e4 100755 --- a/containers/libreportal/frontend/components/apps/core/js/apps-manager.js +++ b/containers/libreportal/frontend/components/apps/core/js/apps-manager.js @@ -373,8 +373,20 @@ class AppsManager { const currentUrl = new URL(window.location.href); targetTab = currentUrl.searchParams.get('tab') || 'config'; } - - const newUrl = window.appPath(appName, targetTab); + + // Preserve the config sub-category (/app//config/) when the URL + // already points at THIS app's config. Without this, rebuilding the URL + // here strips the sub before renderAppDetail reads it back off the path, so + // a cold-load deep-link / refresh of e.g. /app/bookstack/config/ports always + // reset to the first category. Only kept for the same app — a cross-app + // switch intentionally starts at the first category. + let targetSub = null; + if (targetTab === 'config' && window.appPartsFromPath) { + const parts = window.appPartsFromPath(window.location.pathname); + if (parts.tab === 'config' && parts.app === appName) targetSub = parts.sub; + } + + const newUrl = window.appPath(appName, targetTab, targetSub); history.pushState({}, '', newUrl); // Update app-tabbed-manager BEFORE rendering the DOM. If renderAppDetail or