diff --git a/frontend/src/lib/components/home/ImportProjectModal.svelte b/frontend/src/lib/components/home/ImportProjectModal.svelte index b089e9fdda..af372341f0 100644 --- a/frontend/src/lib/components/home/ImportProjectModal.svelte +++ b/frontend/src/lib/components/home/ImportProjectModal.svelte @@ -89,11 +89,13 @@ } /** - * Reloads the caller's list once the run is no longer writing. Immediate for a run that - * has finished, which is the common dismissal — but `abandon()` only stops the *next* - * phase, and the request already sent still lands, so a reload issued at that moment can - * read the list before that write commits and leave it stale again. The cap is there so a - * run that never settles still ends in a reload rather than in nothing. + * The one way this dialog reloads the caller's list: once the run is no longer writing. + * Both exits use it, because both can be taken mid-write — `abandon()` only stops the + * *next* phase and the request already sent still lands, and `done` survives a retry so + * Finish is clickable while the run is going again. A reload issued at either of those + * moments reads the list before the write commits and leaves it stale, which is what the + * reload exists to prevent. Immediate when nothing is running, which is the common case. + * The cap is there so a run that never settles still ends in a reload rather than nothing. */ async function reloadWhenSettled(run: ImportExecution, reload: (() => void) | undefined) { for (let i = 0; i < 60 && run.running; i++) { @@ -205,7 +207,12 @@ if (slug) logFeatureUsage('home', 'template_import', { key: slug }) logFeatureUsage('home', 'template_setup', { key: setupKey(setupOutcome, outstanding) }) finishing = true - onImported?.() + // Through the same deferred reload every closing uses. `done` survives a retry, so + // Finish is clickable while the run is going again — reloading here would read the + // list mid-write, and `finishing` then stops `dismiss()` from reloading after it. + // One reload per closing, always after the writing stops. + if (execution) void reloadWhenSettled(execution, onImported) + else onImported?.() onClose() }