Let the app remember the last open page and reopen it (especially for the PWA) #186
Labels
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/Ponente#186
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This will be useful when we add more features and hierarchy.
🤖 On it — follow along in the action run; the reply will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the task runs.
Pushed
claude/issue-186.What it does
Ponente now reopens on the page you last had open. The manifest's
start_urlis/launch— an endpoint that redirects to whatever page this browser was last on, and to the default board if there is nothing worth reopening.Services/LastPage.csis the rule, and it is one method used in both directions: what may be written down is exactly what may be redirected to, so a hand-edited cookie cannot turn/launchinto an open redirect (ReturnUrl.Sanitizedoes that half, the same way it does for a post-sign-in destination). It's a deny list —/login,/signup,/request,/access-denied,/not-found,/Error,/dev/…and/launchitself are doors and errors, not places — so the "more features and hierarchy" the issue anticipates get remembered without anyone coming back to this file. A denied page leaves the previous one standing, so a detour through sign-in doesn't cost you your board.Decisions worth knowing about:
/launch, not a rule about/./is the default board's own address and the wordmark links to it; a/that bounced you back to where you were would leave no way home and make a bookmark of the board lie. The second address is what separates open the app from open the board.idstays/— it identifies an installed app, so changing it alongsidestart_urlwould turn every existing install into a second icon rather than an updated one.icons.spec.jsnow pins both.prefs-interop.jsthat isn't. The only reader is the server, deciding where to send a launch before it renders anything; kept where only the browser can see it, the feature would have to render the default board in order to leave it. A month's lifetime, where the language cookie gets a year: a language choice doesn't go stale, a location does.?card=) or belongs to a page that isn't remembered anyway.MainLayoutrecords it (first render + everyLocationChanged), because every page renders inside it. 302 withCache-Control: no-store, or a cached launch redirect would pin the app to the first page it ever saw.Verified
dotnet build/dotnet test Ponente.sln— 477 passed, including the newLastPageTests(deny list, query stripping,//evil.example, header injection, self-redirect).dotnet run) and drove it with Playwright:prefs.spec.js(4),icons.spec.js,install.spec.js(11 total), plusboard.spec.js/changelog.spec.jsas a regression check on theMainLayoutchange — 38 passed there, the single failure beingshare.spec.jsasserting the compose stack'slocalhost:8090origin, which a host-run app can't satisfy. No compose runtime in this container, so the suite wasn't run against the real stack./launch,/requestdeliberately not recorded (waiting on the circuit-built.handle-ghostfirst, so it asserts a cookie that wasn't written rather than one that had no chance to be), and/still going home.docs/ui.mdgets a Reopening where you left off section with the reasoning;orientation.mdgets the service row and/launchin the endpoint list,frontend.mdtheprefs-interop.jsnote, andChangelog.Unreleaseda bullet in both locales. One test change beyond the feature:DocumentationTestsonly knew routes mapped from string literals, so it now resolves one mapped through a constant — otherwise/launchwould have read as a documented route the app doesn't serve.No image: the change is a redirect, and a screenshot of the calendar would only show the calendar.
⏱ 17m 23s · 81 turns · tokens: 145.2k in / 54.7k out (+8137.1k cache-read)
📜 Full session transcript
→ Opened PR: #187