fix(panel): warn before a web tab drops unsaved work
Merged
DA
6d ago+310+310+012345678901234567890123456789-27-27-01234567890123456789
Fixes a P1 from the post-merge review of the web app shell: closing, reloading or navigating a web tab threw away unsaved work (an automation draft, say) without asking. The panel's leave guard only watched the panel's own ways out.
What changed
- Panel:
useLeaveGuardtakes an optionalonStandingcallback. It gets the ask each time a page stands one, andundefinedonce the standing ask comes down.Apppasses that on to a new optionalAppPlatform.unsavedWorkhook. The desktop platform leaves the hook out, so the desktop behaves exactly as before, Electron's window close included. - Web (
apps/web/src/app/page-leave.ts, new):- Adds the
beforeunloadlistener only while an ask stands and removes it when the ask comes down, because a listener that is always on keeps the page out of the back-forward cache. - Its
leave(go)sends the tab's own same-tab navigations through the panel's question first. Once the developer says Leave, the browser doesn't ask a second time. - When the back-forward cache brings the page back, the hold applies again.
- Adds the
- The sign-in redirect (
cookieDoorinweb-host.ts) and the refused-popup connect fallback (connect-tab.ts) now go throughleave. Theconnect-tab.tsedit is small: oneleavefield onConnectBrowserand the two fallback lines wrapped in it.
Tests (each fails without the fix)
apps/web/tests/page-leave.test.ts: the browser holds back a close or reload only while work is unsaved, and stops once the ask comes down. A way out asks first, and once the developer says Leave the browser doesn't hold it back. A page restored from the back-forward cache holds back again.apps/web/tests/connect-tab.test.ts: when the popup is refused and the page holds unsaved work, the connect asks before sending the tab to the provider, and only records its return address once told to leave.packages/panel/src/desktop/automations-page.test.ts: the shell hears the ask only while an edit is unsaved. Calling it shows the page's own "Leave with unsaved changes?" dialog, and the shell hears nothing again once the edit is saved.
Known limit
If the developer presses Cancel on a fresh sign-in (signed out → provider), the account source stays in "signing in" until they cancel that themselves. A signed-out panel shows no editor, so this is unlikely to come up. The signInAgain link flow is unaffected.
Made with Luke