/** * Igny8 Image Queue Processor * Sequential image generation with individual progress tracking */ // Process AI Image Generation for Drafts (Sequential Image Processing with Queue Modal) function processAIImageGenerationDrafts(postIds) { console.log('Igny8: processAIImageGenerationDrafts called with postIds:', postIds); // Event 1: Generate Images button clicked if (window.addImageGenDebugLog) { window.addImageGenDebugLog('INFO', 'Generate Images button clicked', { postIds: postIds, timestamp: new Date().toISOString() }); } // Get image generation settings from saved options (passed via wp_localize_script) const desktopEnabled = window.IGNY8_PAGE?.imageSettings?.desktop_enabled || false; const mobileEnabled = window.IGNY8_PAGE?.imageSettings?.mobile_enabled || false; const maxInArticleImages = window.IGNY8_PAGE?.imageSettings?.max_in_article_images || 1; // Event 2: Settings retrieved if (window.addImageGenDebugLog) { window.addImageGenDebugLog('SUCCESS', 'Settings retrieved', { desktop: desktopEnabled, mobile: mobileEnabled, maxImages: maxInArticleImages }); } // Build image queue based on settings const imageQueue = []; postIds.forEach((postId, postIndex) => { // Featured image (always) imageQueue.push({ post_id: postId, post_number: postIndex + 1, type: 'featured', device: '', label: 'Featured Image', post_title: `Post ${postIndex + 1}` }); // Desktop in-article images if (desktopEnabled) { for (let i = 1; i <= maxInArticleImages; i++) { imageQueue.push({ post_id: postId, post_number: postIndex + 1, type: 'article', device: 'desktop', index: i, label: `desktop-${i}`, section: i, post_title: `Post ${postIndex + 1}` }); } } // Mobile in-article images if (mobileEnabled) { for (let i = 1; i <= maxInArticleImages; i++) { imageQueue.push({ post_id: postId, post_number: postIndex + 1, type: 'article', device: 'mobile', index: i, label: `mobile-${i}`, section: i, post_title: `Post ${postIndex + 1}` }); } } }); console.log('Igny8: Image queue built:', imageQueue); // Show queue modal showImageQueueModal(imageQueue, imageQueue.length); // Start processing queue processImageQueue(imageQueue, 0); } // Show modal with image queue and individual progress bars function showImageQueueModal(queue, totalImages) { if (window.currentProgressModal) { window.currentProgressModal.remove(); } const modal = document.createElement('div'); modal.id = 'igny8-image-queue-modal'; modal.className = 'igny8-modal'; let queueHTML = ''; queue.forEach((item, index) => { const itemId = `queue-item-${index}`; queueHTML += `
${index + 1} ${item.label} ${item.post_title} ⏳ Pending
0%
No image
`; }); modal.innerHTML = `

🎨 Generating Images

Total: ${totalImages} images in queue

${queueHTML}
`; document.body.appendChild(modal); modal.classList.add('open'); window.currentProgressModal = modal; } // Process image queue sequentially with progressive loading function processImageQueue(queue, currentIndex) { if (currentIndex >= queue.length) { // All done console.log('Igny8: All images processed'); // Log to Image Generation Debug if (window.addImageGenDebugLog) { window.addImageGenDebugLog('SUCCESS', 'All images processed', { total: queue.length, timestamp: new Date().toISOString() }); } setTimeout(() => { if (window.currentProgressModal) { window.currentProgressModal.remove(); window.currentProgressModal = null; } showNotification('Image generation complete!', 'success'); // Reload table if (window.loadTableData && window.IGNY8_PAGE?.tableId) { window.loadTableData(window.IGNY8_PAGE.tableId); } }, 2000); return; } const item = queue[currentIndex]; const itemElement = document.getElementById(`queue-item-${currentIndex}`); if (!itemElement) { console.error('Queue item element not found:', currentIndex); // Log to Image Generation Debug if (window.addImageGenDebugLog) { window.addImageGenDebugLog('ERROR', 'Queue item element not found', { index: currentIndex, itemId: `queue-item-${currentIndex}` }); } setTimeout(() => processImageQueue(queue, currentIndex + 1), 100); return; } // Update UI to processing itemElement.setAttribute('data-status', 'processing'); itemElement.querySelector('.queue-status').textContent = '⏳ Generating...'; const progressFill = itemElement.querySelector('.queue-progress-fill'); const progressText = itemElement.querySelector('.queue-progress-text'); // Log to Image Generation Debug if (window.addImageGenDebugLog) { window.addImageGenDebugLog('INFO', `Processing ${item.label}`, { postId: item.post_id, type: item.type, device: item.device || 'N/A', index: item.index || 1, queuePosition: `${currentIndex + 1}/${queue.length}` }); } // Progressive loading: 50% in 7s, 75% in next 5s, then 5% every second until 95% let currentProgress = 0; let phase = 1; let phaseStartTime = Date.now(); const progressInterval = setInterval(() => { const elapsed = Date.now() - phaseStartTime; if (phase === 1 && currentProgress < 50) { // Phase 1: 0% to 50% in 7 seconds (7.14% per second) currentProgress += 0.714; if (currentProgress >= 50 || elapsed >= 7000) { currentProgress = 50; phase = 2; phaseStartTime = Date.now(); } } else if (phase === 2 && currentProgress < 75) { // Phase 2: 50% to 75% in 5 seconds (5% per second) currentProgress += 0.5; if (currentProgress >= 75 || elapsed >= 5000) { currentProgress = 75; phase = 3; phaseStartTime = Date.now(); } } else if (phase === 3 && currentProgress < 95) { // Phase 3: 75% to 95% - 5% every second if (elapsed >= 1000) { currentProgress = Math.min(95, currentProgress + 5); phaseStartTime = Date.now(); } } progressFill.style.width = currentProgress + '%'; progressText.textContent = Math.round(currentProgress) + '%'; }, 100); // Generate single image const formData = new FormData(); formData.append('action', 'igny8_ai_generate_single_image'); formData.append('nonce', window.IGNY8_PAGE.nonce); formData.append('post_id', item.post_id); formData.append('type', item.type); formData.append('device', item.device || ''); formData.append('index', item.index || 1); // Add meta box integration fields formData.append('image_label', item.label || ''); formData.append('section', item.section || ''); fetch(window.IGNY8_PAGE.ajaxUrl, { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { // Stop progressive loading clearInterval(progressInterval); if (data.success) { // Success - complete to 100% progressFill.style.width = '100%'; progressText.textContent = '100%'; itemElement.setAttribute('data-status', 'completed'); itemElement.querySelector('.queue-status').textContent = '✅ Complete'; // Display thumbnail if image URL is available if (data.data?.image_url) { const thumbnailDiv = itemElement.querySelector('.queue-thumbnail'); if (thumbnailDiv) { thumbnailDiv.innerHTML = `Generated image`; } } console.log(`✓ Image ${currentIndex + 1} generated successfully`); // Log to Image Generation Debug if (window.addImageGenDebugLog) { window.addImageGenDebugLog('SUCCESS', `${item.label} generated successfully`, { postId: item.post_id, attachmentId: data.data?.attachment_id, provider: data.data?.provider, queuePosition: `${currentIndex + 1}/${queue.length}` }); } // Process next image after short delay setTimeout(() => processImageQueue(queue, currentIndex + 1), 500); } else { // Error - show at 90% progressFill.style.width = '90%'; progressText.textContent = 'Failed'; itemElement.setAttribute('data-status', 'failed'); itemElement.querySelector('.queue-status').textContent = '❌ Failed'; const errorDiv = itemElement.querySelector('.queue-error'); errorDiv.textContent = data.data?.message || 'Unknown error'; errorDiv.style.display = 'block'; console.error(`✗ Image ${currentIndex + 1} failed:`, data.data?.message); // Log to Image Generation Debug if (window.addImageGenDebugLog) { window.addImageGenDebugLog('ERROR', `${item.label} generation failed`, { postId: item.post_id, error: data.data?.message || 'Unknown error', queuePosition: `${currentIndex + 1}/${queue.length}` }); } // Continue to next image despite error setTimeout(() => processImageQueue(queue, currentIndex + 1), 1000); } }) .catch(error => { // Exception - stop progressive loading clearInterval(progressInterval); progressFill.style.width = '90%'; progressText.textContent = 'Error'; itemElement.setAttribute('data-status', 'failed'); itemElement.querySelector('.queue-status').textContent = '❌ Error'; const errorDiv = itemElement.querySelector('.queue-error'); errorDiv.textContent = 'Exception: ' + error.message; errorDiv.style.display = 'block'; console.error(`✗ Image ${currentIndex + 1} exception:`, error); // Log to Image Generation Debug if (window.addImageGenDebugLog) { window.addImageGenDebugLog('ERROR', `${item.label} request exception`, { postId: item.post_id, error: error.message, queuePosition: `${currentIndex + 1}/${queue.length}` }); } // Continue to next image despite error setTimeout(() => processImageQueue(queue, currentIndex + 1), 1000); }); }