Skip to content

Commit d218031

Browse files
imnasnainaecclaude
andauthored
Fix confirmation overlay not closing properly when errors occur (#120)
* Address code review comments on save-draft-project draft persistence - Move setPendingReplace(undefined) into finally in handleConfirmReplace so the DiscardDraftConfirm dialog always dismisses even if a future refactor makes openProject or startNewDraft throwable - Add comments documenting the fire-and-forget persistence design and its failure-visibility trade-offs (dirty flag set optimistically, backend notification as the sole user signal) - Add comment on the transient stale dirty indicator when sourceProjectId changes mid-load (self-corrects; nearly unreachable in practice) - Add comment explaining why getDraftSnapshot is called at render time in ProjectModals (ref read is allocation-free; only consumed by saveAs branch) - Add comment clarifying that per-row Overwrite buttons open the inline confirmation dialog rather than triggering a save Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Nix less-important comments --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3d68073 commit d218031

2 files changed

Lines changed: 8 additions & 1 deletion

File tree

src/components/modals/ProjectModals.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ export default function ProjectModals({
270270
}
271271
} finally {
272272
setIsReplacing(false);
273+
setPendingReplace(undefined);
273274
}
274-
setPendingReplace(undefined);
275275
}, [isReplacing, openProject, pendingReplace, startNewDraft]);
276276

277277
/** Cancels the deferred action, returning to the underlying modal with the draft untouched. */

src/hooks/useDraftProject.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ export default function useDraftProject(
135135
* Persists `draft` to storage, fire-and-forget. The backend surfaces an error notification on
136136
* failure; here we only log so a rejected write never throws into a render or event handler.
137137
*
138+
* Note: the draft is the **only** persistence path — there is no secondary write on blur or
139+
* unmount that would retry a failed autosave. If storage is unavailable during editing, the
140+
* backend sends one error notification per failed write; if that notification itself fails (the
141+
* `.catch(() => {})` in `main.ts`), edits made in that window are silently lost on the next page
142+
* refresh. The tab title's `●` marker stays lit because `dirty` is set optimistically before the
143+
* write, not in response to its outcome.
144+
*
138145
* @param draft - The draft envelope to write.
139146
*/
140147
const persist = useCallback(

0 commit comments

Comments
 (0)