From eaa92738dcdb8a4bdc800c8ef4a50bb8635bb103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Thu, 3 Sep 2026 12:37:14 +0100 Subject: [PATCH] =?UTF-8?q?give=20:section=20back=20=E2=80=94=20the=20spla?= =?UTF-8?q?t=20took=20it=20from=20fifteen=20plugins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `/` and `//:section` are what every plugin has always had, and fifteen of them read useParams().section. Replacing the pair with a splat took that parameter away from all of them at once: the screens still mounted and every one lost its selection, which is worse than a 404 because nothing says so. The splat stays, for depth. React-router ranks a static or dynamic segment above it, so a plugin with one segment gets `section` again and only deeper paths fall through. Co-Authored-By: Claude Opus 5 (1M context) --- src/apps/officer-web/App.tsx | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/apps/officer-web/App.tsx b/src/apps/officer-web/App.tsx index 3c0bd7cf..364ee675 100644 --- a/src/apps/officer-web/App.tsx +++ b/src/apps/officer-web/App.tsx @@ -101,24 +101,31 @@ export function App() { {/* One route per SCREEN, not per plugin — `screenId` is the key, because a plugin with two screens (caldav: Calendar and Contacts) contributes two entries sharing one `appName`. */} {/* - A SPLAT, so the whole subtree is the plugin's. + Three routes, and the third is the only new one. - It was a pair — the bare route and `/:section` — which gave a plugin exactly one segment and - made the platform the author of what it meant. Anything deeper had to go in the query - string, and `/fofos-admin/layout/header` was not expressible at all. + `/` and `//:section` are what every plugin has always had, and fifteen of + them read `useParams().section`. A splat ALONE replaced that for a day and took the + parameter away from all of them at once — the screens still mounted and every one of them + lost its selection, which is a worse failure than a 404 because nothing says so. - A splat matches zero segments too, so this is one route where there were two, and the - plugin reads its own position off the location. Routing inside a plugin is the plugin's, - which is the same line `mountPrefix` already draws around its API: the platform owns where - a plugin STARTS and nothing after it. + The splat is added for depth rather than instead of them: `/fofos-admin/layout/header` was + not expressible before, and a plugin that wants its own subtree reads the location. + React-router ranks a static or dynamic segment above a splat, so a plugin with one segment + still gets `section` and only deeper paths fall through. */} - {installedPlugins.map((plugin) => ( + {installedPlugins.flatMap((plugin) => [ + } />, } + />, + } - /> - ))} + />, + ])} } /> } /> {/* TEMPORARY / EXPERIMENTAL — offline file transfer over animated QR codes */}