(file, container, skipThumbnail = false)
| 12508 | const afterCount = pendingTagData.length; |
| 12509 | |
| 12510 | if (beforeCount !== afterCount) { |
| 12511 | console.log(`batch-tag-generation-complete: Removed ${beforeCount - afterCount} duplicates. Now have ${afterCount} entries`); |
| 12512 | } |
| 12513 | |
| 12514 | // Use showTagPreviewDialog directly with the deduplicated data |
| 12515 | // Don't call updateTagPreviewDialog which might use stale data |
| 12516 | showTagPreviewDialog(pendingTagData); |
| 12517 | } |
| 12518 | |
| 12519 | // Don't auto-close - let the user review what happened (even if no tags) |
| 12520 | // They can see which models failed and which succeeded |
| 12521 | }; |
| 12522 | if (window._electronPendingEvents['batch-tag-generation-complete']) { |
| 12523 | window._electronPendingEvents['batch-tag-generation-complete'].forEach((args) => { |
| 12524 | window._electronRealEventHandlers['batch-tag-generation-complete'].apply(null, args); |
| 12525 | }); |
| 12526 | delete window._electronPendingEvents['batch-tag-generation-complete']; |
| 12527 | } |
| 12528 | |
| 12529 | // Function to show tag preview dialog (now handles multiple models) |
| 12530 | function showTagPreviewDialog(modelsData) { |
| 12531 | const dialog = document.getElementById('tag-preview-dialog'); |
| 12532 | const container = document.getElementById('tag-preview-container'); |
| 12533 | const modelInfoEl = document.getElementById('tag-preview-model-info'); |
| 12534 | |
| 12535 | if (!dialog || !container) { |
| 12536 | console.error('Tag preview dialog elements not found'); |
| 12537 | return; |
| 12538 | } |
| 12539 | |
| 12540 | const renderGeneration = ++tagPreviewDialogRenderGeneration; |
| 12541 | |
| 12542 | // Check if dialog is open BEFORE we use it (fix race condition). |
| 12543 | // A close during in-flight generation sets suppressTagPreviewReopen; do not |
| 12544 | // reopen or rewrite the dialog from a call that started before that close. |
| 12545 | const isDialogOpen = dialog.open === true; |
| 12546 | if (!isDialogOpen && suppressTagPreviewReopen) { |
| 12547 | return; |
| 12548 | } |
| 12549 | reviewDialogOpen = isDialogOpen; |
| 12550 | |
| 12551 | // When dialog is already open, ALWAYS use pendingTagData as the single source of truth |
| 12552 | // This prevents stale data from being displayed and ensures consistency |
| 12553 | let dataToDeduplicate; |
| 12554 | if (isDialogOpen) { |
| 12555 | // Dialog is open - ONLY use pendingTagData (ignore passed parameter) |
| 12556 | // pendingTagData is already updated by updatePendingTagData before this is called |
| 12557 | dataToDeduplicate = pendingTagData; |
| 12558 | } else { |
| 12559 | // Dialog not open yet - use passed data (first time opening) |
| 12560 | dataToDeduplicate = modelsData; |
| 12561 | } |
| 12562 | |
| 12563 | // Deduplicate models by filePath - prefer entries with actual tags over "Generating..." entries |
| 12564 | const beforeDedup = dataToDeduplicate.length; |
| 12565 | const uniqueModelsData = deduplicateModelData(dataToDeduplicate); |
| 12566 | const afterDedup = uniqueModelsData.length; |
| 12567 |
no test coverage detected