diff --git a/web/js/admin.js b/web/js/admin.js index 0846fa1..3de40b4 100644 --- a/web/js/admin.js +++ b/web/js/admin.js @@ -10,8 +10,6 @@ this.categories = []; this.tags = []; this.subfolders = []; - this.imageViewMode = 'fit'; // 'fit' or 'full' - this.naturalImageSize = { width: 0, height: 0 }; // Pagination state this.pagination = { @@ -280,7 +278,6 @@ const response = await fetch("/prompt_manager/stats"); if (response.ok) { const data = await response.json(); - console.log("Stats response:", data); // Debug log if (data.success) { // Try different possible response structures @@ -1066,7 +1063,6 @@ } async setRating(promptId, rating) { - console.log(`Setting rating for prompt ${promptId} to ${rating}`); // Update UI immediately for better UX const ratingElement = document.querySelector(`[data-id="${promptId}"][data-rating]`); @@ -2123,7 +2119,7 @@ throw new Error(data.message); } } catch (e) { - console.log('Non-JSON line:', line); + console.warn('Non-JSON line:', line); } } } @@ -2486,374 +2482,6 @@ } - - async parsePNGMetadata(arrayBuffer) { - const dataView = new DataView(arrayBuffer); - let offset = 8; // Skip PNG signature - const metadata = {}; - let chunkCount = 0; - - console.log('Starting PNG metadata parsing...'); - - while (offset < arrayBuffer.byteLength - 8) { - const length = dataView.getUint32(offset); - const type = new TextDecoder().decode(arrayBuffer.slice(offset + 4, offset + 8)); - - chunkCount++; - console.log(`Chunk ${chunkCount}: type=${type}, length=${length}`); - - if (type === 'tEXt' || type === 'iTXt' || type === 'zTXt') { - const chunkData = arrayBuffer.slice(offset + 8, offset + 8 + length); - let text; - - if (type === 'tEXt') { - text = new TextDecoder().decode(chunkData); - } else if (type === 'iTXt') { - // iTXt format: keyword\0compression\0language\0translated_keyword\0text - const textData = new TextDecoder().decode(chunkData); - const parts = textData.split('\0'); - console.log(`iTXt parts count: ${parts.length}, first part: ${parts[0]}`); - if (parts.length >= 5) { - metadata[parts[0]] = parts[4]; - } - text = textData; - } else if (type === 'zTXt') { - // zTXt is compressed - basic parsing (might need proper decompression) - text = new TextDecoder().decode(chunkData); - } - - // Parse the text chunk for key-value pairs - const nullIndex = text.indexOf('\0'); - if (nullIndex !== -1) { - const key = text.substring(0, nullIndex); - const value = text.substring(nullIndex + 1); - console.log(`Found metadata: ${key} = ${value.substring(0, 100)}...`); - metadata[key] = value; - } - } - - offset += 8 + length + 4; // Move to next chunk (8 = length + type, 4 = CRC) - } - - console.log(`Parsed ${chunkCount} chunks, found ${Object.keys(metadata).length} metadata items`); - return metadata; - } - - extractComfyUIData(metadata) { - // Look for ComfyUI workflow data in various possible fields - let workflowData = null; - let promptData = null; - - // Common ComfyUI metadata field names - const workflowFields = ['workflow', 'Workflow', 'comfy', 'ComfyUI']; - const promptFields = ['prompt', 'Prompt', 'parameters', 'Parameters']; - - for (const field of workflowFields) { - if (metadata[field]) { - try { - // Clean NaN values from JSON string before parsing - let cleanedJson = metadata[field]; - cleanedJson = cleanedJson.replace(/:\s*NaN\b/g, ': null'); - cleanedJson = cleanedJson.replace(/\bNaN\b/g, 'null'); - - workflowData = JSON.parse(cleanedJson); - console.log(`Successfully parsed workflow field: ${field}`); - break; - } catch (e) { - console.log('Failed to parse workflow field:', field, e.message); - } - } - } - - for (const field of promptFields) { - if (metadata[field]) { - try { - // Clean NaN values from JSON string before parsing - let cleanedJson = metadata[field]; - cleanedJson = cleanedJson.replace(/:\s*NaN\b/g, ': null'); - cleanedJson = cleanedJson.replace(/\bNaN\b/g, 'null'); - - promptData = JSON.parse(cleanedJson); - console.log(`Successfully parsed prompt field: ${field}`); - break; - } catch (e) { - console.log('Failed to parse prompt field:', field, e.message); - console.log('Raw data:', metadata[field].substring(0, 200) + '...'); - } - } - } - - return { workflow: workflowData, prompt: promptData }; - } - - updateMetadataPanel(comfyData, imageSrc) { - const metadataContent = document.getElementById('metadataContent'); - if (!metadataContent) return; - - // Get the actual file path from current image data - let filePath = imageSrc; // fallback to URL - if (this.currentGalleryImages && this.currentImageIndex !== null && this.currentGalleryImages[this.currentImageIndex]) { - const currentImage = this.currentGalleryImages[this.currentImageIndex]; - filePath = currentImage.image_path || currentImage.filename || imageSrc; - } - - // Trace prompts, model and sampler settings through the node graph (#75) - const { - checkpoint, positivePrompt, negativePrompt, steps, cfgScale, sampler, seed, - } = window.ComfyMetadata.extractGenerationParams(comfyData); - - // Store the current metadata for copying - this.currentMetadata = { - positivePrompt, - negativePrompt, - checkpoint, - steps, - cfgScale, - sampler, - seed, - workflow: comfyData.workflow, - prompt: comfyData.prompt - }; - - // Update the HTML - metadataContent.innerHTML = ` - -
-

File Path

-
- ${escapeHtml(filePath)} -
-
- - -
-

Resources used

-
-
-
${escapeHtml(checkpoint)}
-
ComfyUI Generated
-
- CHECKPOINT -
-
- - -
-
-

Prompt

- COMFYUI - -
-
- ${escapeHtml(positivePrompt.substring(0, 200))}${positivePrompt.length > 200 ? '...' : ''} -
- ${positivePrompt.length > 200 ? '' : ''} -
- - -
-
-

Negative prompt

- -
-
- ${escapeHtml(negativePrompt.substring(0, 200))}${negativePrompt.length > 200 ? '...' : ''} -
- ${negativePrompt.length > 200 ? '' : ''} -
- - -
-

Other metadata

-
- CFG SCALE: ${escapeHtml(cfgScale)} - STEPS: ${escapeHtml(steps)} - SAMPLER: ${escapeHtml(sampler)} -
-
- SEED: ${escapeHtml(seed)} -
-
- - -
-

ComfyUI Workflow

-
- - -
-
- `; - } - - showMetadataError() { - const metadataContent = document.getElementById('metadataContent'); - if (!metadataContent) return; - - metadataContent.innerHTML = ` -
- - - -

Error Loading Metadata

-

Could not extract ComfyUI metadata from this image

-
- `; - } - - async copyPrompt(type) { - if (!this.currentMetadata) { - this.showNotification('❌ No metadata available for copying', 'error'); - return; - } - - const text = type === 'positive' ? this.currentMetadata.positivePrompt : this.currentMetadata.negativePrompt; - - if (!text || text === 'No prompt found' || text === 'No negative prompt found') { - this.showNotification(`❌ No ${type} prompt available`, 'error'); - return; - } - - await this.copyToClipboard(text); - } - - async tryFallbackMetadata(imageSrc) { - console.log('Trying fallback metadata extraction for:', imageSrc); - - try { - // Try to get prompt from current gallery image data - let fallbackPrompt = 'No prompt found'; - - if (this.currentGalleryImages && this.currentImageIndex !== null && this.currentGalleryImages[this.currentImageIndex]) { - const currentImage = this.currentGalleryImages[this.currentImageIndex]; - console.log('Current image data:', currentImage); - - // If we have prompt_id, try to get the prompt from our local prompts array - if (currentImage.prompt_id && this.prompts) { - const prompt = this.prompts.find(p => p.id === currentImage.prompt_id); - if (prompt) { - fallbackPrompt = prompt.text; - console.log('Found prompt from database:', fallbackPrompt.substring(0, 100)); - } - } - } - - // Set fallback metadata - this.currentMetadata = { - positivePrompt: fallbackPrompt, - negativePrompt: 'No negative prompt found', - checkpoint: 'Unknown', - steps: 'Unknown', - cfgScale: 'Unknown', - sampler: 'Unknown', - seed: 'Unknown', - workflow: null, - prompt: null - }; - - // Update metadata panel with fallback data - this.updateMetadataPanel({}, imageSrc); - - } catch (error) { - console.error('Fallback metadata extraction failed:', error); - this.showMetadataError(); - - // Set empty metadata as last resort - this.currentMetadata = { - positivePrompt: 'No prompt found', - negativePrompt: 'No negative prompt found', - checkpoint: 'Unknown', - steps: 'Unknown', - cfgScale: 'Unknown', - sampler: 'Unknown', - seed: 'Unknown', - workflow: null, - prompt: null - }; - } - } - - async copyAllMetadata() { - if (!this.currentMetadata) return; - - const allData = `Checkpoint: ${this.currentMetadata.checkpoint || 'Unknown'} -Positive Prompt: ${this.currentMetadata.positivePrompt} -Negative Prompt: ${this.currentMetadata.negativePrompt} -Steps: ${this.currentMetadata.steps || 'Unknown'} -CFG Scale: ${this.currentMetadata.cfgScale || 'Unknown'} -Sampler: ${this.currentMetadata.sampler || 'Unknown'} -Seed: ${this.currentMetadata.seed || 'Unknown'}`; - - await this.copyToClipboard(allData); - } - - showFullPrompt(type) { - if (!this.currentMetadata) return; - - const prompt = type === 'positive' ? this.currentMetadata.positivePrompt : this.currentMetadata.negativePrompt; - const safeType = escapeHtml(type.charAt(0).toUpperCase() + type.slice(1)); - const newWindow = window.open('', '_blank'); - const doc = newWindow.document; - doc.open(); - doc.write('' + safeType + ' Prompt'); - doc.close(); - doc.body.style.cssText = 'background:#111;color:#fff;font-family:monospace;padding:20px;'; - const h2 = doc.createElement('h2'); - h2.textContent = type.charAt(0).toUpperCase() + type.slice(1) + ' Prompt'; - doc.body.appendChild(h2); - const pre = doc.createElement('pre'); - pre.style.cssText = 'background:#222;padding:15px;border-radius:5px;white-space:pre-wrap;line-height:1.5;'; - pre.textContent = prompt; - doc.body.appendChild(pre); - const btn = doc.createElement('button'); - btn.textContent = 'Copy to Clipboard'; - btn.style.cssText = 'margin-top:20px;padding:10px 20px;background:#444;color:#fff;border:none;border-radius:5px;cursor:pointer;'; - btn.addEventListener('click', () => { navigator.clipboard.writeText(pre.textContent).then(() => alert('Copied!')); }); - doc.body.appendChild(btn); - } - - showWorkflowData() { - if (!this.currentMetadata || !this.currentMetadata.workflow) return; - - const newWindow = window.open('', '_blank'); - newWindow.document.write(` - - ComfyUI Workflow Data - -

ComfyUI Workflow JSON

-
${JSON.stringify(this.currentMetadata.workflow, null, 2)}
- - - `); - } - - downloadWorkflowJSON() { - if (!this.currentMetadata || !this.currentMetadata.workflow) return; - - const dataStr = JSON.stringify(this.currentMetadata.workflow, null, 2); - const dataBlob = new Blob([dataStr], {type: 'application/json'}); - const url = URL.createObjectURL(dataBlob); - const link = document.createElement('a'); - link.href = url; - link.download = 'comfyui_workflow.json'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - } - async copyToClipboard(text) { try { await navigator.clipboard.writeText(text); @@ -2927,7 +2555,7 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; workflowData = JSON.parse(cleanedJson); break; } catch (e) { - console.log('Failed to parse workflow field:', field); + console.warn('Failed to parse workflow field:', field); } } } @@ -2943,7 +2571,7 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; promptData = JSON.parse(cleanedJson); break; } catch (e) { - console.log('Failed to parse prompt field:', field); + console.warn('Failed to parse prompt field:', field); } } } @@ -4263,31 +3891,10 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; } }); - // Keyboard shortcuts for modals - document.addEventListener('keydown', function(e) { - if (e.key === 'Escape') { - // Close any open modals - if (document.getElementById('galleryModal') && !document.getElementById('galleryModal').classList.contains('hidden')) { - admin.closeGallery(); - } else if (document.getElementById('imageViewerModal') && !document.getElementById('imageViewerModal').classList.contains('hidden')) { - admin.closeImageViewer(); - } - } else if (document.getElementById('imageViewerModal') && !document.getElementById('imageViewerModal').classList.contains('hidden')) { - // Handle arrow keys in image viewer - if (e.key === 'ArrowLeft') { - e.preventDefault(); - admin.previousImage(); - } else if (e.key === 'ArrowRight') { - e.preventDefault(); - admin.nextImage(); - } - } - }); - - // Window resize listener for responsive image sizing - window.addEventListener('resize', function() { - // Only apply resize adjustments if image viewer is open and in fit mode - if (document.getElementById('imageViewerModal') && !document.getElementById('imageViewerModal').classList.contains('hidden') && admin.imageViewMode === 'fit') { - admin.applyImageSizing(); + // Escape closes the gallery modal + document.addEventListener('keydown', function (e) { + const galleryModal = document.getElementById('galleryModal'); + if (e.key === 'Escape' && galleryModal && !galleryModal.classList.contains('hidden')) { + admin.closeGallery(); } }); diff --git a/web/js/gallery.js b/web/js/gallery.js index f54607c..058b902 100644 --- a/web/js/gallery.js +++ b/web/js/gallery.js @@ -557,17 +557,14 @@ className: '', title: [1, (image, imageData) => `${imageData.alt} (${this.images.length} images) - Original Image`], viewed: (event) => { - console.log('ViewerJS opened original image for metadata'); // Add metadata sidebar when ViewerJS opens // Use the original image URL from data-original attribute const originalImg = event.detail.originalImage; setTimeout(() => this.addMetadataSidebar(originalImg), 100); }, show: function() { - console.log('Viewer shown - displaying original image'); }, shown: function() { - console.log('ViewerJS initialization complete - ready for metadata'); }, hide: function() { // Remove sidebar when viewer closes @@ -628,7 +625,6 @@ // Load metadata for the current image (ALWAYS use original for metadata) const originalImageUrl = originalImage.dataset.original || originalImage.src; - console.log('Loading metadata from original image:', originalImageUrl); this.loadImageMetadata(originalImageUrl, sidebar.querySelector('#metadata-content')); // Listen for ViewerJS view changes to update metadata @@ -683,7 +679,6 @@ const isVideo = img.dataset.isVideo === 'true'; const mediaType = img.dataset.mediaType || 'image'; - console.log('Opening original media for viewing:', originalMediaUrl, 'Type:', mediaType); if (isVideo) { // For videos, use our custom video modal @@ -1519,33 +1514,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; return div.textContent; } - showNotification(message, type = 'info') { - const notification = document.createElement('div'); - notification.className = `fixed top-4 right-4 px-4 py-2 rounded-pm-md shadow-pm text-sm z-[20000] transition-all duration-300 transform translate-x-full`; - - const colors = { - success: "bg-pm-success text-pm", - error: "bg-pm-error text-pm", - warning: "bg-pm-warning text-pm", - info: "bg-pm-accent text-pm" - }; - - notification.className += ` ${colors[type] || colors.info}`; - notification.textContent = message; - - document.body.appendChild(notification); - - setTimeout(() => notification.classList.remove("translate-x-full"), 100); - setTimeout(() => { - notification.classList.add("translate-x-full"); - setTimeout(() => { - if (notification.parentNode) { - document.body.removeChild(notification); - } - }, 300); - }, 3000); - } - formatImageCaption(image) { const date = new Date(image.modified_time * 1000); return `${image.filename} | ${this.formatFileSize(image.size)} | ${date.toLocaleString()}`; @@ -1630,7 +1598,7 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; workflowData = JSON.parse(cleanedJson); break; } catch (e) { - console.log('Failed to parse workflow field:', field); + console.warn('Failed to parse workflow field:', field); } } } @@ -1646,7 +1614,7 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; promptData = JSON.parse(cleanedJson); break; } catch (e) { - console.log('Failed to parse prompt field:', field); + console.warn('Failed to parse prompt field:', field); } } } @@ -1900,13 +1868,11 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Show cancel button cancelBtn.classList.remove('hidden'); - console.log(`Starting thumbnail generation with quality: ${options.quality}`); // Set up Server-Sent Events const eventSource = new EventSource(`/prompt_manager/images/generate-thumbnails/progress?quality=${options.quality}`); // Log connection - console.log('EventSource connected for thumbnail generation progress'); let cancelled = false; let resultData = null; @@ -1935,7 +1901,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Log status updates if (this.getSettings().debugMode) { - console.log(`Thumbnail generation status: ${data.phase} - ${data.message}`); } }); @@ -1955,7 +1920,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Log start event if (this.getSettings().debugMode) { - console.log(`Thumbnail generation started: ${data.total_images} files to process`); } }); @@ -1987,7 +1951,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Log to console for debugging if debug mode is enabled if (this.getSettings().debugMode) { - console.log(`Thumbnail generation progress: ${data.processed}/${data.total_images} - ${data.current_file}`); } }); @@ -2015,7 +1978,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Log completion details if (this.getSettings().debugMode) { - console.log('Thumbnail generation completed:', resultData); if (resultData.errors && resultData.errors.length > 0) { console.warn('Thumbnail generation errors:', resultData.errors); } @@ -2050,7 +2012,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Check if connection is closing normally if (eventSource.readyState === EventSource.CLOSED) { - console.log('EventSource connection closed'); } else { console.error('EventSource connection failed'); } @@ -2103,7 +2064,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; if (response.ok) { const data = await response.json(); - console.log('Server thumbnails cleared:', data); } } catch (e) { console.warn('Could not clear server thumbnails:', e); @@ -2646,7 +2606,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Get quality setting const quality = this.getSettings().imageQuality || 'medium'; - console.log(`Starting modal thumbnail generation with quality: ${quality}`); // Set up Server-Sent Events (same as the settings modal) const eventSource = new EventSource(`/prompt_manager/images/generate-thumbnails/progress?quality=${quality}`); @@ -2764,7 +2723,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; addStatusMessage(`Successfully generated ${resultData.count} new thumbnails, skipped ${resultData.skipped} existing`, 'success'); } - console.log('Modal thumbnail generation completed:', resultData); // Clean up eventSource.close(); @@ -2807,7 +2765,6 @@ Seed: ${this.currentMetadata.seed || 'Unknown'}`; // Check if connection is closing normally (after complete event) if (eventSource.readyState === EventSource.CLOSED && resultData) { - console.log('EventSource connection closed normally after completion'); return; } diff --git a/web/metadata.html b/web/metadata.html index ec5c92e..6a80fca 100644 --- a/web/metadata.html +++ b/web/metadata.html @@ -162,7 +162,7 @@ Seed: ${currentWorkflowData.seed || 'Unknown'}`; workflowData = JSON.parse(cleanedJson); break; } catch (e) { - console.log('Failed to parse workflow field:', field, e); + console.warn('Failed to parse workflow field:', field, e); } } } @@ -178,7 +178,7 @@ Seed: ${currentWorkflowData.seed || 'Unknown'}`; promptData = JSON.parse(cleanedJson); break; } catch (e) { - console.log('Failed to parse prompt field:', field, e); + console.warn('Failed to parse prompt field:', field, e); } } } @@ -351,8 +351,6 @@ Seed: ${currentWorkflowData.seed || 'Unknown'}`; // Update data panel updateDataPanel(comfyData, file.name); - console.log('Extracted metadata:', metadata); - console.log('ComfyUI data:', comfyData); } catch (error) { console.error('Error processing image:', error);