diff --git a/js/chat/chat-init.js b/js/chat/chat-init.js index f2882d2..06d7b5b 100644 --- a/js/chat/chat-init.js +++ b/js/chat/chat-init.js @@ -259,40 +259,64 @@ document.addEventListener("DOMContentLoaded", () => { }; const createImageElement = (url, msgIndex) => { const imageId = `img-${msgIndex}-${Date.now()}`; - localStorage.setItem(`imageId_${msgIndex}`, imageId); - const imageContainer = document.createElement("div"); - imageContainer.className = "ai-image-container"; - const loadingDiv = document.createElement("div"); - loadingDiv.className = "ai-image-loading"; - const spinner = document.createElement("div"); - spinner.className = "loading-spinner"; - loadingDiv.appendChild(spinner); - Object.assign(loadingDiv.style, { width: "512px", height: "512px" }); - imageContainer.appendChild(loadingDiv); - const img = document.createElement("img"); - img.src = url; - img.alt = "AI Generated Image"; - img.className = "ai-generated-image"; - img.style.display = "none"; - img.dataset.imageUrl = url; - img.dataset.imageId = imageId; - img.crossOrigin = "anonymous"; - img.onload = () => { - loadingDiv.remove(); - img.style.display = "block"; - attachImageButtonListeners(img, imageId); - }; - img.onerror = () => { - loadingDiv.innerHTML = "⚠️ Failed to load image"; - loadingDiv.style.display = "flex"; - loadingDiv.style.justifyContent = "center"; - loadingDiv.style.alignItems = "center"; - }; - imageContainer.appendChild(img); - const imgButtonContainer = document.createElement("div"); - imgButtonContainer.className = "image-button-container"; + localStorage.setItem(`imageId_${msgIndex}`, imageId); + const imageContainer = document.createElement("div"); + imageContainer.className = "ai-image-container"; + const loadingDiv = document.createElement("div"); + loadingDiv.className = "ai-image-loading"; + const spinner = document.createElement("div"); + spinner.className = "loading-spinner"; + loadingDiv.appendChild(spinner); + Object.assign(loadingDiv.style, { width: "512px", height: "512px" }); + imageContainer.appendChild(loadingDiv); + const img = document.createElement("img"); + img.alt = "AI Generated Image"; + img.className = "ai-generated-image"; + img.style.display = "none"; + img.dataset.imageUrl = url; + img.dataset.imageId = imageId; + img.crossOrigin = "anonymous"; + imageContainer.appendChild(img); + const imgButtonContainer = document.createElement("div"); + imgButtonContainer.className = "image-button-container"; imgButtonContainer.dataset.imageId = imageId; imageContainer.appendChild(imgButtonContainer); + + const loadViaPolli = async () => { + try { + const u = new URL(url); + const parts = u.pathname.split('/'); + const i = parts.indexOf('prompt'); + const prompt = i >= 0 && parts[i + 1] ? decodeURIComponent(parts[i + 1]) : ''; + const model = u.searchParams.get('model') || undefined; + const width = u.searchParams.get('width') ? Number(u.searchParams.get('width')) : undefined; + const height = u.searchParams.get('height') ? Number(u.searchParams.get('height')) : undefined; + if (window.polliLib && window.polliClient && prompt) { + const data = await window.polliLib.image(prompt, { model, width, height, json: true }, window.polliClient); + const src = data?.url ? data.url : URL.createObjectURL(data); + img.src = src; + } else { + img.src = url; + } + } catch (e) { + console.warn('polliLib image failed', e); + img.src = url; + } + }; + + img.onload = () => { + loadingDiv.remove(); + img.style.display = "block"; + attachImageButtonListeners(img, imageId); + }; + img.onerror = () => { + loadingDiv.innerHTML = "⚠️ Failed to load image"; + loadingDiv.style.display = "flex"; + loadingDiv.style.justifyContent = "center"; + loadingDiv.style.alignItems = "center"; + }; + + loadViaPolli(); return imageContainer; }; const createAudioElement = (url) => { diff --git a/js/chat/chat-storage.js b/js/chat/chat-storage.js index afa67cf..1caa7bb 100644 --- a/js/chat/chat-storage.js +++ b/js/chat/chat-storage.js @@ -156,24 +156,51 @@ document.addEventListener("DOMContentLoaded", () => { } function createImageElement(url) { const imageId = `voice-img-${Date.now()}`; - localStorage.setItem(`voiceImageId_${imageId}`, imageId); - const imageContainer = document.createElement("div"); - imageContainer.className = "ai-image-container"; - const loadingDiv = document.createElement("div"); - loadingDiv.className = "ai-image-loading"; - const spinner = document.createElement("div"); - spinner.className = "loading-spinner"; - loadingDiv.appendChild(spinner); - Object.assign(loadingDiv.style, { width: "512px", height: "512px" }); - imageContainer.appendChild(loadingDiv); - const img = document.createElement("img"); - img.src = url; - img.alt = "AI Generated Image"; - img.className = "ai-generated-image"; - img.style.display = "none"; - img.dataset.imageUrl = url; - img.dataset.imageId = imageId; - img.crossOrigin = "anonymous"; + localStorage.setItem(`voiceImageId_${imageId}`, imageId); + const imageContainer = document.createElement("div"); + imageContainer.className = "ai-image-container"; + const loadingDiv = document.createElement("div"); + loadingDiv.className = "ai-image-loading"; + const spinner = document.createElement("div"); + spinner.className = "loading-spinner"; + loadingDiv.appendChild(spinner); + Object.assign(loadingDiv.style, { width: "512px", height: "512px" }); + imageContainer.appendChild(loadingDiv); + const img = document.createElement("img"); + img.alt = "AI Generated Image"; + img.className = "ai-generated-image"; + img.style.display = "none"; + img.dataset.imageUrl = url; + img.dataset.imageId = imageId; + img.crossOrigin = "anonymous"; + imageContainer.appendChild(img); + const imgButtonContainer = document.createElement("div"); + imgButtonContainer.className = "image-button-container"; + imgButtonContainer.dataset.imageId = imageId; + imageContainer.appendChild(imgButtonContainer); + + const loadViaPolli = async () => { + try { + const u = new URL(url); + const parts = u.pathname.split('/'); + const i = parts.indexOf('prompt'); + const prompt = i >= 0 && parts[i + 1] ? decodeURIComponent(parts[i + 1]) : ''; + const model = u.searchParams.get('model') || undefined; + const width = u.searchParams.get('width') ? Number(u.searchParams.get('width')) : undefined; + const height = u.searchParams.get('height') ? Number(u.searchParams.get('height')) : undefined; + if (window.polliLib && window.polliClient && prompt) { + const data = await window.polliLib.image(prompt, { model, width, height, json: true }, window.polliClient); + const src = data?.url ? data.url : URL.createObjectURL(data); + img.src = src; + } else { + img.src = url; + } + } catch (e) { + console.warn('polliLib image failed', e); + img.src = url; + } + }; + let attempts = 0; const maxAttempts = 5; const tryReload = () => { @@ -184,21 +211,17 @@ document.addEventListener("DOMContentLoaded", () => { loadingDiv.style.alignItems = "center"; return; } - setTimeout(() => { - img.src = url + (url.includes('?') ? '&' : '?') + 'retry=' + Date.now(); - }, 1000 * attempts); + setTimeout(loadViaPolli, 1000 * attempts); }; + img.onload = () => { loadingDiv.remove(); img.style.display = "block"; attachImageButtons(img, imageId); }; img.onerror = tryReload; - imageContainer.appendChild(img); - const imgButtonContainer = document.createElement("div"); - imgButtonContainer.className = "image-button-container"; - imgButtonContainer.dataset.imageId = imageId; - imageContainer.appendChild(imgButtonContainer); + + loadViaPolli(); return imageContainer; }