437 lines
16 KiB
JavaScript
437 lines
16 KiB
JavaScript
/**
|
|
* 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 += `
|
|
<div class="queue-item" id="${itemId}" data-status="pending">
|
|
<div style="display: flex; gap: 10px; align-items: center;">
|
|
<div style="flex: 1;">
|
|
<div class="queue-item-header">
|
|
<span class="queue-number">${index + 1}</span>
|
|
<span class="queue-label">${item.label}</span>
|
|
<span class="queue-post-title">${item.post_title}</span>
|
|
<span class="queue-status">⏳ Pending</span>
|
|
</div>
|
|
<div class="queue-progress-bar">
|
|
<div class="queue-progress-fill" style="width: 0%"></div>
|
|
<div class="queue-progress-text">0%</div>
|
|
</div>
|
|
<div class="queue-error" style="display: none;"></div>
|
|
</div>
|
|
<div class="queue-thumbnail" style="width: 75px; height: 75px; background: #f0f0f0; border-radius: 4px; display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0;">
|
|
<span style="color: #999; font-size: 11px;">No image</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
modal.innerHTML = `
|
|
<div class="igny8-modal-content" style="max-width: 950px; max-height: 80vh; overflow-y: auto;">
|
|
<div class="igny8-modal-header">
|
|
<h3>🎨 Generating Images</h3>
|
|
<p style="margin: 5px 0; color: var(--text-light);">Total: ${totalImages} images in queue</p>
|
|
</div>
|
|
<div class="igny8-modal-body">
|
|
<div class="image-queue-container">
|
|
${queueHTML}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<style>
|
|
.queue-item {
|
|
margin-bottom: 12px;
|
|
padding: 12px;
|
|
background: var(--panel-2);
|
|
border-radius: 8px;
|
|
border: 1px solid var(--border);
|
|
}
|
|
.queue-item[data-status="processing"] {
|
|
background: rgba(59, 130, 246, 0.1);
|
|
border-color: rgb(59, 130, 246);
|
|
}
|
|
.queue-item[data-status="completed"] {
|
|
background: rgba(16, 185, 129, 0.1);
|
|
border-color: rgb(16, 185, 129);
|
|
}
|
|
.queue-item[data-status="failed"] {
|
|
background: rgba(239, 68, 68, 0.1);
|
|
border-color: rgb(239, 68, 68);
|
|
}
|
|
.queue-item-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 8px;
|
|
font-size: 13px;
|
|
}
|
|
.queue-number {
|
|
background: rgb(59, 130, 246);
|
|
color: white;
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 11px;
|
|
font-weight: bold;
|
|
}
|
|
.queue-label {
|
|
font-weight: 600;
|
|
}
|
|
.queue-post-title {
|
|
flex: 1;
|
|
font-size: 12px;
|
|
opacity: 0.7;
|
|
}
|
|
.queue-status {
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
}
|
|
.queue-progress-bar {
|
|
height: 20px;
|
|
background: rgba(0,0,0,0.1);
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
.queue-progress-fill {
|
|
height: 100%;
|
|
background: rgb(59, 130, 246);
|
|
transition: width 0.3s ease;
|
|
}
|
|
.queue-progress-text {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
font-size: 11px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
text-shadow: 0 0 3px rgba(255,255,255,0.8);
|
|
}
|
|
.queue-item[data-status="completed"] .queue-progress-fill {
|
|
background: rgb(16, 185, 129);
|
|
}
|
|
.queue-item[data-status="failed"] .queue-progress-fill {
|
|
background: rgb(239, 68, 68);
|
|
}
|
|
.queue-error {
|
|
margin-top: 8px;
|
|
padding: 8px;
|
|
background: rgba(239, 68, 68, 0.1);
|
|
border-left: 3px solid rgb(239, 68, 68);
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
}
|
|
</style>
|
|
`;
|
|
|
|
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 = `<img src="${data.data.image_url}" style="width: 100%; height: 100%; object-fit: cover; border-radius: 4px;" alt="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);
|
|
});
|
|
}
|