feat: warn before leaving a form with unsaved changes
Drag-dropping page images then clicking a nav link silently discarded the whole form. Add a reusable guardUnsavedChanges helper (SvelteKit beforeNavigate confirm + native beforeunload) and wire it into the manga upload, manga edit, and chapter upload forms. The dirty check returns false while submitting so the post-save redirect isn't prompted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
36
frontend/src/lib/unsaved-guard.ts
Normal file
36
frontend/src/lib/unsaved-guard.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { beforeNavigate } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
/**
|
||||
* Warn before leaving a page with unsaved form state. Call once from a
|
||||
* component's script (during init). `isDirty` is read live on each navigation,
|
||||
* so pass a closure over the form's reactive state — and have it return `false`
|
||||
* once a save has succeeded (or is in flight) so the post-save redirect doesn't
|
||||
* prompt.
|
||||
*
|
||||
* Covers both in-app navigation (SvelteKit `beforeNavigate`, with a confirm) and
|
||||
* full-page unload / tab close / reload (the native `beforeunload` prompt).
|
||||
*/
|
||||
export function guardUnsavedChanges(isDirty: () => boolean): void {
|
||||
beforeNavigate((nav) => {
|
||||
// `leave` (tab close / reload) can't show a custom confirm here — the
|
||||
// beforeunload handler below covers it. Only guard in-app navigations.
|
||||
if (nav.type === 'leave') return;
|
||||
if (!isDirty()) return;
|
||||
if (!confirm('You have unsaved changes. Leave this page and discard them?')) {
|
||||
nav.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
const handler = (e: BeforeUnloadEvent) => {
|
||||
if (isDirty()) {
|
||||
e.preventDefault();
|
||||
// Legacy browsers require returnValue to be set.
|
||||
e.returnValue = '';
|
||||
}
|
||||
};
|
||||
window.addEventListener('beforeunload', handler);
|
||||
return () => window.removeEventListener('beforeunload', handler);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user