|
382 | 382 | } |
383 | 383 | // Cancel navigation first, then show async modal and navigate if confirmed |
384 | 384 | cancel(); |
385 | | - showUnsavedChangesModal( |
| 385 | + resolveUnsavedChanges( |
386 | 386 | 'There are unsaved changes. What would you like to do before leaving this page?', |
387 | | - 'Unsaved Changes', |
388 | 387 | 'Save and Leave', |
389 | 388 | 'Discard and Leave', |
390 | 389 | 'Stay on Page', |
391 | | - ).then(async ({ confirm, value }) => { |
392 | | - if (!confirm || !to?.url) { |
393 | | - return; |
394 | | - } |
395 | | - if (value?.shouldSave && !(await saveActiveDocument())) { |
396 | | - // Save failed or was cancelled — stay on the page so edits aren't lost. |
| 390 | + ).then(decision => { |
| 391 | + if (decision === 'stay' || !to?.url) { |
397 | 392 | return; |
398 | 393 | } |
399 | 394 | // Reset content to allow navigation without re-triggering the modal |
|
420 | 415 | if (!$activeDocumentIsDirty) { |
421 | 416 | return true; |
422 | 417 | } |
423 | | - const { confirm, value } = await showUnsavedChangesModal( |
| 418 | + const decision = await resolveUnsavedChanges( |
424 | 419 | 'There are unsaved changes. What would you like to do before navigating away from the current file?', |
425 | | - 'Unsaved Changes', |
426 | 420 | 'Save and Navigate', |
427 | 421 | 'Discard and Navigate', |
428 | 422 | 'Keep Editing', |
429 | 423 | ); |
430 | | - if (!confirm) { |
| 424 | + if (decision === 'stay') { |
431 | 425 | return false; |
432 | 426 | } |
433 | | - if (value?.shouldSave) { |
434 | | - // Only proceed if the save actually persisted; otherwise stay so edits aren't lost. |
435 | | - return await saveActiveDocument(); |
| 427 | + if (decision === 'proceed-discarded') { |
| 428 | + // Discard: mark clean so navigation proceeds without re-prompting. |
| 429 | + activeDocument.markClean(); |
436 | 430 | } |
437 | | - // Discard: mark clean so navigation proceeds without re-prompting. |
438 | | - activeDocument.markClean(); |
439 | 431 | return true; |
440 | 432 | } |
441 | 433 |
|
|
805 | 797 | return false; |
806 | 798 | } |
807 | 799 |
|
| 800 | + /** |
| 801 | + * Prompts the user about unsaved changes and resolves the save/discard decision so callers |
| 802 | + * don't have to reimplement the modal + save-attempt dance. Returns: |
| 803 | + * - 'stay': user cancelled, or chose Save but the save failed/was cancelled — do not navigate. |
| 804 | + * - 'proceed-saved': document was saved (and marked clean); safe to navigate. |
| 805 | + * - 'proceed-discarded': user chose to discard; caller decides whether to revert content. |
| 806 | + * Callers own the post-decision action (goto / replaceState / content-mode switch) and any |
| 807 | + * discard-time content revert, since those differ per call site. |
| 808 | + */ |
| 809 | + async function resolveUnsavedChanges( |
| 810 | + message: string, |
| 811 | + confirmSaveLabel: string, |
| 812 | + confirmDiscardLabel: string, |
| 813 | + cancelLabel: string, |
| 814 | + ): Promise<'stay' | 'proceed-saved' | 'proceed-discarded'> { |
| 815 | + const { confirm, value } = await showUnsavedChangesModal( |
| 816 | + message, |
| 817 | + 'Unsaved Changes', |
| 818 | + confirmSaveLabel, |
| 819 | + confirmDiscardLabel, |
| 820 | + cancelLabel, |
| 821 | + ); |
| 822 | + if (!confirm) { |
| 823 | + return 'stay'; |
| 824 | + } |
| 825 | + if (value?.shouldSave) { |
| 826 | + // Save failed or was cancelled — stay so edits aren't lost. |
| 827 | + return (await saveActiveDocument()) ? 'proceed-saved' : 'stay'; |
| 828 | + } |
| 829 | + return 'proceed-discarded'; |
| 830 | + } |
| 831 | +
|
808 | 832 | async function confirmAndNavigate(filePath: string | null) { |
809 | 833 | if (!(await confirmNavigateAway())) { |
810 | 834 | return false; |
|
1280 | 1304 | ) { |
1281 | 1305 | // Guard against switching away from dirty file |
1282 | 1306 | if ($workspaceContentMode === WorkspaceContentMode.File && $activeDocumentIsDirty) { |
1283 | | - const { confirm, value } = await showUnsavedChangesModal( |
| 1307 | + const decision = await resolveUnsavedChanges( |
1284 | 1308 | 'There are unsaved changes. What would you like to do before navigating away from the current file?', |
1285 | | - 'Unsaved Changes', |
1286 | 1309 | 'Save and Navigate', |
1287 | 1310 | 'Discard and Navigate', |
1288 | 1311 | 'Keep Editing', |
1289 | 1312 | ); |
1290 | | - if (!confirm) { |
| 1313 | + if (decision === 'stay') { |
1291 | 1314 | return; |
1292 | 1315 | } |
1293 | | - if (value?.shouldSave) { |
1294 | | - if (!(await saveActiveDocument())) { |
1295 | | - // Save failed or was cancelled — stay on the current file so edits aren't lost. |
1296 | | - return; |
1297 | | - } |
1298 | | - } else { |
| 1316 | + if (decision === 'proceed-discarded') { |
1299 | 1317 | // Discard: revert content to last-saved state and mark clean |
1300 | 1318 | activeDocument.updateContent($activeDocument.originalContent); |
1301 | 1319 | activeDocument.markClean(); |
|
0 commit comments