File manager - Edit - /home/meharhashir55/gptai55/index.html
Back
<html lang="en"> <head> <meta charset="UTF-8" /> <!-- Viewport meta tag for responsiveness --> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>AI Chatbot</title> <script src="https://js.puter.com/v2/"></script> <style> /* Reset & Global Styles */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: Arial, sans-serif; background: #f4f4f9; width: 100%; max-width: 100vw; } /* Container Layout */ .container { display: flex; height: 100vh; width: 100%; max-width: 100vw; overflow: hidden; } /* Sidebar Styles β desktop and mobile */ #sidebar { width: 250px; background: #fff; border-right: 1px solid #ddd; padding: 20px; overflow-y: auto; transition: transform 0.3s ease, width 0.3s ease, padding 0.3s ease; z-index: 1500; } #sidebar.collapsed { width: 60px; padding: 10px; } @media (max-width: 1920px) { #sidebar { height:70vh; } } @media (max-width: 600px) { #sidebar { position: fixed; top: 0; left: 0; height: 50vh; width: 250px; padding: 20px; transform: translateX(-100%); box-shadow: 2px 0 5px rgba(0, 0, 0, 0.3); z-index: 2000; } #sidebar.open { transform: translateX(0); } } /* Sidebar Header */ #sidebar-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; } #sidebar-header h2 { font-size: 20px; color: #007bff; white-space: nowrap; } #sidebar.collapsed #sidebar-header h2 { display: none; } #sidebar-toggle { background: none; border: none; font-size: 22px; cursor: pointer; color: #007bff; } /* Option Buttons (Sidebar Menu) */ .option-buttons { display: flex; flex-direction: column; gap: 10px; } .option-buttons button, .option-buttons select { padding: 10px 15px; font-size: 16px; border-radius: 6px; border: none; cursor: pointer; background: #007bff; color: white; transition: background 0.3s; text-align: left; white-space: nowrap; } .option-buttons button:hover, .option-buttons select:hover { background: #0056b3; } .option-buttons select { background: #fff; color: #333; border: 1px solid #ccc; } #sidebar.collapsed .option-text { display: none; } .custom-file-label { display: inline-block; padding: 10px 15px; font-size: 16px; border-radius: 6px; background: #007bff; color: white; cursor: pointer; transition: background 0.3s; text-align: left; } .custom-file-label:hover { background: #0056b3; } /* Main Content Area */ #main { flex-grow: 1; display: flex; flex-direction: column; position: relative; } /* Chat Header */ .chat-header { background: #007bff; color: white; padding: 15px 15px 15px 60px; font-size: 22px; text-align: center; width: 100%; max-width: 100vw; position: relative; z-index: 1000; } #menuToggle { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); background: none; border: none; font-size: 26px; color: white; cursor: pointer; display: none; z-index: 1100; } @media (max-width: 600px) { #menuToggle { display: block; } .chat-header { padding-left: 60px; text-align: center; max-width:100vw; position: fixed; } .chat-box { max-width:100vw; } } /* Chat Box */ .chat-box { width: 100%; max-width: 100vw; padding: 15px; margin-bottom:15vh; margin-top:10vh; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; z-index: 900; box-sizing: border-box; } /* Chat Input Container with Toolbar */ .chat-input-container { padding: 10px 15px; border-top: 1px solid #ccc; background: #fff; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1100; } /* New toolbar area for attach/search/voice/reason icons */ .chat-toolbar { display: flex; gap: 10px; margin-bottom: 5px; } .chat-toolbar button { background: none; border: none; font-size: 20px; cursor: pointer; color: #007bff; } .chat-input-area { display: flex; gap: 10px; align-items: center; } .chat-input { flex-grow: 1; height: 60px; border: 1px solid #ccc; border-radius: 8px; padding: 12px; font-size: 16px; resize: none; } .send-button, .stop-button { padding: 12px 20px; border: none; border-radius: 8px; cursor: pointer; white-space: nowrap; font-size: 16px; } .send-button { background: #007bff; color: white; transition: background 0.3s; } .send-button:hover { background: #0056b3; } .stop-button { background: #dc3545; color: white; display: none; } /* Attachment Preview β if a file is attached */ .attachment-preview { display: flex; align-items: center; gap: 10px; margin-bottom: 5px; border: 1px solid #ccc; padding: 5px; border-radius: 6px; } .attachment-preview img { max-width: 50px; max-height: 50px; } .attachment-preview .file-name { font-size: 14px; color: #333; } .attachment-preview .remove-attachment { background: none; border: none; color: #dc3545; cursor: pointer; font-size: 16px; } /* Chat Messages */ .chat-message { padding: 12px; border-radius: 8px; max-width: 75%; line-height: 1.8; white-space: pre-wrap; word-break: break-word; } .chat-message pre { font-family: "Courier New", Consolas, monospace; background-color: #f4f4f4; padding: 12px; border-radius: 5px; overflow-x: auto; white-space: pre-wrap; word-break: normal; font-size: 14px; } .user-message { align-self: flex-end; background: #007bff; color: white; } .bot-message { align-self: flex-start; background: #e9ecef; color: #333; } /* Generated Image Container with Thumbnail & Download Option */ .generated-img-container { position: relative; display: inline-block; max-width: 200px; /* thumbnail size */ max-height: 200px; overflow: hidden; margin-bottom: 10px; } .generated-img-container img { display: block; width: 100%; height: auto; } .download-btn { position: absolute; bottom: 5px; right: 5px; background: rgba(0,0,0,0.5); color: #fff; border: none; border-radius: 4px; padding: 5px 10px; cursor: pointer; font-size: 12px; } /* Spinner */ .spinner { border: 4px solid rgba(0,0,0,0.1); width: 36px; height: 36px; border-radius: 50%; border-left-color: #09f; animation: spin 1s ease infinite; margin: 0 auto; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Hide File Inputs */ .file-input { display: none; } /* Mobile Only Adjustments */ @media (max-width: 768px) { .chat-input { height: 60px; } .send-button, .stop-button { flex-shrink: 0; } } </style> </head> <body> <div class="container"> <!-- Sidebar Menu --> <div id="sidebar"> <div id="sidebar-header"> <h2>Menu</h2> <button id="sidebar-toggle" onclick="toggleSidebar()">β°</button> </div> <div class="option-buttons"> <button onclick="sendMessage()"><span class="option-text">π¬ Chat</span></button> <button onclick="setSearchType('web')">π Web Search</button> <button onclick="setSearchType('journal')">π Journal Search</button> <button onclick="triggerImageUpload()"><span class="option-text">πΌοΈ Upload Image</span></button> <button onclick="triggerFileUpload()"><span class="option-text">π Upload File</span></button> <select id="modelSelector"> <option value="gpt-4o-mini">GPT-4o Mini (OpenAI)</option> <option value="o3-mini">GPT-4o (OpenAI)</option> <option value="o3-mini">O3 Mini (OpenAI)</option> <option value="claude">Claude</option> <option value="claude-3-5-sonnet">Claude 3.5 Sonnet (Anthropic)</option> <option value="deepseek-chat">DeepSeek Chat (High-Flyer)</option> <option value="deepseek-reasoner">DeepSeek R1 (High-Flyer)</option> <option value="gemini-2.0-flash">Gemini 2.0 Flash (Google)</option> <option value="gemini-1.5-flash">Gemini 1.5 Flash (Google)</option> <option value="meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo">Meta Llama 3.1 8B Instruct Turbo (Together.ai)</option> <option value="meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo">Meta Llama 3.1 70B Instruct Turbo (Together.ai)</option> <option value="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo">Meta Llama 3.1 405B Instruct Turbo (Together.ai)</option> <option value="mistral-large-latest">Mistral Large Latest (Mistral AI)</option> <option value="pixtral-large-latest">Pixtral Large Latest (Mistral AI)</option> <option value="codestral-latest">Codestral Latest (Mistral AI)</option> <option value="google/gemma-2-27b-it">Gemma 2.27B IT (Groq)</option> <option value="grok-beta">Grok Beta (xAI)</option> </select> <button onclick="launchCameraDescriber()"><span class="option-text">π· Camera Describer</span></button> <button onclick="generateImage()"><span class="option-text">πΌοΈ Generate Image</span></button> <button onclick="extractTextFromImage()"><span class="option-text">π Extract Text</span></button> <button onclick="chatWithGPT4Vision()"><span class="option-text">π GPTβ4 Vision Chat</span></button> <button onclick="manualSignIn()"><span class="option-text">π Sign In</span></button> </div> </div> <!-- Main Area --> <div id="main"> <div class="chat-header"> <button id="menuToggle" onclick="mobileToggleSidebar()">β°</button> AI Chatbot </div> <div class="chat-box" id="chatBox" onclick="hideSidebarMobile()"></div> <!-- Chat Input Container --> <div class="chat-input-container" id="chatInputContainer"> <!-- Attachment Preview (appears if a file is attached) --> <div id="attachmentPreview" class="attachment-preview" style="display:none;"></div> <!-- Chat Toolbar with icons --> <div class="chat-toolbar"> <button id="attachButton" onclick="toggleAttachMenu()">π</button> <button id="searchButton" onclick="triggerWebSearch()">π</button> <button id="reasonButton" onclick="triggerReason()">π‘</button> <button id="voiceButton" onclick="toggleVoiceRecording()">ποΈ</button> </div> <!-- Optional attach menu (hidden by default) --> <div id="attachMenu" style="display:none; margin-bottom:5px;"> <button onclick="document.getElementById('imageInput').click()">Attach Image</button> <button onclick="document.getElementById('fileInput').click()">Attach File</button> </div> <div class="chat-input-area"> <textarea class="chat-input" id="chatInput" placeholder="Type your message..." onkeydown="handleKeyPress(event)"></textarea> <button class="send-button" onclick="sendMessage()" id="sendButton">Send</button> <button class="stop-button" onclick="stopStreaming()" id="stopButton">Stop</button> </div> </div> <!-- Hidden Camera Container --> <div id="cameraContainer" onclick="hideSidebarMobile()"> <video id="cameraVideo" width="320" height="240" autoplay></video> <canvas id="cameraCanvas" width="320" height="240" style="display: none;"></canvas> <div class="button-group"> <button id="describePhoto" disabled>Describe Photo Using AI</button> <button onclick="closeCameraDescriber()">Back</button> </div> <div id="output"></div> </div> </div> </div> <!-- Hidden File Inputs --> <input type="file" class="file-input" id="imageInput" accept="image/*" onchange="handleFileAttachment(event, 'image')" /> <input type="file" class="file-input" id="fileInput" accept="application/pdf,.doc,.docx,.txt" onchange="handleFileAttachment(event, 'file')" /> <input type="file" class="file-input" id="textImageInput" accept="image/*" onchange="processExtractText()" /> <input type="file" class="file-input" id="visionImageInput" accept="image/*" onchange="processVisionChat()" /> <script> // ------------------------------- // Global Variables & Authentication // ------------------------------- const messages = JSON.parse(localStorage.getItem("chatHistory")) || []; let isSignedIn = false; let authToken = localStorage.getItem("authToken"); if (authToken) { isSignedIn = true; } // For streaming chat: store controller so that Stop button can cancel the stream. let streamAbortController = null; async function autoSignIn() { const username = "Mehar5"; const password = "Meharmehar5@@5"; try { const response = await puter.auth.signIn({ username, password }); authToken = response.token; localStorage.setItem("authToken", authToken); isSignedIn = true; alert("You have been signed in automatically!"); } catch (error) { console.error("Sign-in failed:", error); alert("Sign-in failed. Please try again."); } } if (!isSignedIn) { autoSignIn(); } // ------------------------------- // Chat History & Message Functions // ------------------------------- let searchType; function setSearchType(type) { searchType = type; alert(`Search set to: ${type.toUpperCase()}`); } function displayChatHistory() { const chatHistory = JSON.parse(localStorage.getItem("chatHistory")) || []; const chatBox = document.getElementById("chatBox"); chatBox.innerHTML = ""; chatHistory.forEach((msg) => { const messageDiv = document.createElement("div"); if (msg.role === "system") { messageDiv.classList.add("chat-message", "bot-message"); chatBox.appendChild(messageDiv); processCodeResponse(msg.content, messageDiv, chatBox); } else { messageDiv.classList.add("chat-message", "user-message"); messageDiv.textContent = msg.content; chatBox.appendChild(messageDiv); } }); chatBox.scrollTop = chatBox.scrollHeight; } function saveMessage(text, sender) { if (!text || text.trim() === "") return; const chatHistory = JSON.parse(localStorage.getItem('chatHistory')) || []; chatHistory.push({ content: text.trim(), role: sender }); if (chatHistory.length > 10) { chatHistory.splice(0, chatHistory.length - 10); } localStorage.setItem('chatHistory', JSON.stringify(chatHistory)); messages.push({ content: text.trim(), role: sender }); if (messages.length > 10) { messages.splice(0, messages.length - 10); } } async function sendMessage() { // If a streaming response is in progress you might want to disable send. // For this demo we assume that clicking Send always triggers a new message. const input = document.getElementById("chatInput"); const message = input.value.trim(); if (!message && !attachedFile) return; const chatBox = document.getElementById("chatBox"); // Append attached-file info if available (preview text) let finalMessage = message; if (attachedFile) { finalMessage = "[Attached File: " + attachedFile.name + "] " + message; } // Append user message const userMsg = document.createElement("div"); userMsg.classList.add("chat-message", "user-message"); userMsg.textContent = finalMessage; chatBox.appendChild(userMsg); input.value = ""; removeAttachmentPreview(); chatBox.scrollTop = chatBox.scrollHeight; saveMessage(finalMessage, "user"); // Append placeholder for bot response const botMsg = document.createElement("div"); botMsg.classList.add("chat-message", "bot-message"); botMsg.innerHTML = "<p>Thinking...</p>"; chatBox.appendChild(botMsg); chatBox.scrollTop = chatBox.scrollHeight; // Start streaming response β enable Stop button document.getElementById("stopButton").style.display = "inline-block"; document.getElementById("sendButton").style.display = "none"; streamAbortController = new AbortController(); const selectedModel = document.getElementById("modelSelector").value; let resp; let finalResponse = ""; try { if (searchType === "web"){ const webData = await fetchWebData(message); botMsg.innerHTML = "<p>Searching...</p>"; resp = await puter.ai.chat([ { content: message, role: "user" }, { content: webData, refusal:null, role: "system" } ], false, { model: selectedModel, stream: true, signal: streamAbortController.signal }); } else { resp = await puter.ai.chat(messages, { model: selectedModel, stream: true, signal: streamAbortController.signal }); } botMsg.textContent = ""; for await (const part of resp) { finalResponse += part?.text || ""; botMsg.textContent = finalResponse; chatBox.scrollTop = chatBox.scrollHeight; } } catch(error) { if (error.name === "AbortError") { botMsg.innerText = "Response cancelled."; } else { if (error.error.delegate === "usage-limited-chat") { botMsg.textContent = "Your chat limit has been reached. Please create another account for free use."; return; } } } processCodeResponse(finalResponse, botMsg, chatBox); saveMessage(finalResponse.trim(), "system"); // Reset Stop / Send buttons document.getElementById("stopButton").style.display = "none"; document.getElementById("sendButton").style.display = "inline-block"; } // Stop streaming response β called when user clicks Stop function stopStreaming() { if (streamAbortController) { streamAbortController.abort(); streamAbortController = null; document.getElementById("stopButton").style.display = "none"; document.getElementById("sendButton").style.display = "inline-block"; } } // ------------------------------- // Code Response Processing Function // ------------------------------- function processCodeResponse(responseText, botMsg, chatBox) { const text = responseText.trim(); const delimiterRegex = /^[\-\_]{4,}$/m; if (!delimiterRegex.test(text)) { const isCode = /<\s*!DOCTYPE html|function\s+\w+\s*\(|\bclass\s+\w+\b|#include\s+<.*?>|def\s+\w+\(|\bpublic\s+(class|static)\b|\bvar\s+\w+\s*=|console\.log\(|document\.querySelector\(/.test(text); if (!isCode) { botMsg.innerHTML = `<p>${escapeHTML(text)}</p>`; chatBox.scrollTop = chatBox.scrollHeight; return; } botMsg.innerHTML = `<pre>${escapeHTML(text)}</pre>`; chatBox.scrollTop = chatBox.scrollHeight; return; } let parts = text.split(/\n(?:[\-\_]{4,})\n/); let outputHtml = ""; parts.forEach((part, index) => { let trimmedPart = part.trim(); if (!trimmedPart) return; if (index % 2 === 0) { outputHtml += `<p style="margin:5px 0;">${escapeHTML(trimmedPart)}</p>`; } else { let lines = trimmedPart.split("\n"); let fileName = null; const fileHeaderMatch = lines[0].match(/^File:\s*(.+)$/); if (fileHeaderMatch) { fileName = fileHeaderMatch[1].trim(); lines.shift(); } let codeSnippet = lines.join("\n").trim(); const codeBlockId = "codeBlock_" + index; if (fileName) { outputHtml += `<div style="margin:5px 0; padding:5px; border:1px solid #ccc;"> <strong>File: ${escapeHTML(fileName)}</strong><br><br>`; } else { outputHtml += `<div style="margin:5px 0; padding:5px; border:1px solid #ccc;">`; } outputHtml += `<pre style="margin:0; padding:0;"><code id="${codeBlockId}">${escapeHTML(codeSnippet)}</code></pre> <button class="copy-code-button" onclick="copyCode(this, '${codeBlockId}')">Copy Code</button></div>`; } }); botMsg.innerHTML = outputHtml; chatBox.scrollTop = chatBox.scrollHeight; } function escapeHTML(text) { var map = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }; return text.replace(/[&<>"']/g, (m) => map[m]); } function copyCode(button, codeBlockId) { const codeBlock = document.getElementById(codeBlockId); if (codeBlock) { const txt = codeBlock.innerText; if (!navigator.clipboard) { const textArea = document.createElement("textarea"); textArea.value = txt; document.body.appendChild(textArea); textArea.select(); try { document.execCommand("copy"); const orig = button.innerText; button.innerText = "Copied!"; setTimeout(() => { button.innerText = orig; }, 2000); } catch (error) { console.error("Fallback: Unable to copy", error); } document.body.removeChild(textArea); } else { navigator.clipboard.writeText(txt).then(() => { const orig = button.innerText; button.innerText = "Copied!"; setTimeout(() => { button.innerText = orig; }, 2000); }).catch(err => console.error("Async: Could not copy text:", err)); } } } function handleKeyPress(event) { if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); sendMessage(); } } // ------------------------------- // File/Image Upload Functions & Attachment Preview // ------------------------------- let attachedFile = null; function toggleAttachMenu() { const menu = document.getElementById("attachMenu"); menu.style.display = (menu.style.display === "none") ? "block" : "none"; } function handleFileAttachment(event, type) { const file = event.target.files[0]; if (file) { attachedFile = file; showAttachmentPreview(file, type); } // Hide attach menu afterwards. document.getElementById("attachMenu").style.display = "none"; } function showAttachmentPreview(file, type) { const previewDiv = document.getElementById("attachmentPreview"); previewDiv.innerHTML = ""; if (type === "image") { const img = document.createElement("img"); img.src = URL.createObjectURL(file); previewDiv.appendChild(img); } const span = document.createElement("span"); span.className = "file-name"; span.textContent = file.name; previewDiv.appendChild(span); const removeBtn = document.createElement("button"); removeBtn.className = "remove-attachment"; removeBtn.textContent = "β"; removeBtn.onclick = removeAttachmentPreview; previewDiv.appendChild(removeBtn); previewDiv.style.display = "flex"; } function removeAttachmentPreview() { attachedFile = null; const previewDiv = document.getElementById("attachmentPreview"); previewDiv.innerHTML = ""; previewDiv.style.display = "none"; } function triggerImageUpload() { document.getElementById("imageInput").click(); } function triggerFileUpload() { document.getElementById("fileInput").click(); } async function uploadImage() { const file = document.getElementById("imageInput").files[0]; if (file) { const chatBox = document.getElementById("chatBox"); const userMsg = document.createElement("div"); userMsg.classList.add("chat-message", "user-message"); userMsg.textContent = "Sending image for analysis..."; chatBox.appendChild(userMsg); chatBox.scrollTop = chatBox.scrollHeight; const imageUrl = URL.createObjectURL(file); const resp = await puter.ai.chat("What do you see?", imageUrl); const responseText = await resp.text(); const botMsg = document.createElement("div"); botMsg.classList.add("chat-message", "bot-message"); botMsg.textContent = responseText; chatBox.appendChild(botMsg); chatBox.scrollTop = chatBox.scrollHeight; saveMessage("Sending image for analysis...", "user"); saveMessage(responseText, "system"); } } async function uploadFile() { const file = document.getElementById("fileInput").files[0]; if (file) { const chatBox = document.getElementById("chatBox"); const userMsg = document.createElement("div"); userMsg.classList.add("chat-message", "user-message"); userMsg.textContent = "Uploading file for analysis..."; chatBox.appendChild(userMsg); chatBox.scrollTop = chatBox.scrollHeight; const fileUrl = URL.createObjectURL(file); const resp = await puter.ai.chat("Analyze this file", fileUrl); const responseText = await resp.text(); const botMsg = document.createElement("div"); botMsg.classList.add("chat-message", "bot-message"); botMsg.textContent = responseText; chatBox.appendChild(botMsg); chatBox.scrollTop = chatBox.scrollHeight; saveMessage("Uploading file for analysis...", "user"); saveMessage(responseText, "system"); } } // ------------------------------- // New Features: Camera, Generate Image, Text Extraction, GPTβ4 Vision, Manual SignβIn // ------------------------------- let cameraStream = null; function launchCameraDescriber() { document.getElementById("chatBox").style.display = "none"; document.getElementById("chatInputContainer").style.display = "none"; document.getElementById("cameraContainer").style.display = "block"; const describeBtn = document.getElementById("describePhoto"); describeBtn.disabled = true; const video = document.getElementById("cameraVideo"); navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { cameraStream = stream; video.srcObject = stream; describeBtn.disabled = false; }) .catch(err => { console.error("Error accessing camera:", err); alert("Unable to access camera."); }); } function closeCameraDescriber() { if (cameraStream) { cameraStream.getTracks().forEach(track => track.stop()); cameraStream = null; } document.getElementById("cameraContainer").style.display = "none"; document.getElementById("chatBox").style.display = "flex"; document.getElementById("chatInputContainer").style.display = "flex"; } document.getElementById("describePhoto").addEventListener("click", () => { const video = document.getElementById("cameraVideo"); const canvas = document.getElementById("cameraCanvas"); const outputDiv = document.getElementById("output"); const context = canvas.getContext("2d"); context.drawImage(video, 0, 0, canvas.width, canvas.height); const imageData = canvas.toDataURL("image/png"); outputDiv.innerHTML = '<div class="spinner"></div>'; document.getElementById("describePhoto").disabled = true; puter.ai.chat("Describe this image", imageData) .then(response => { outputDiv.innerText = 'Image Description: ' + response; document.getElementById("describePhoto").disabled = false; }) .catch(err => { console.error("Error in describing image:", err); outputDiv.innerText = "Error in getting description"; document.getElementById("describePhoto").disabled = false; }); }); async function generateImage() { const promptStr = prompt("Enter prompt for image generation:"); if (!promptStr) return; const chatBox = document.getElementById("chatBox"); const loadingMsg = document.createElement("div"); loadingMsg.classList.add("chat-message", "bot-message"); loadingMsg.innerHTML = '<div class="spinner"></div>'; chatBox.appendChild(loadingMsg); chatBox.scrollTop = chatBox.scrollHeight; try { // Assume puter.ai.txt2img returns an image element const imgEl = await puter.ai.txt2img(promptStr, false); // Set full resolution attributes (the original image will be 1080x1080) imgEl.width = 1080; imgEl.height = 1080; // Remove loading message loadingMsg.remove(); // Create a thumbnail preview container const imgContainer = document.createElement("div"); imgContainer.classList.add("generated-img-container"); // For display purposes, set the image to fill the container. imgEl.style.width = "100%"; imgEl.style.height = "auto"; // Download button β when clicked, downloads the original image const downloadBtn = document.createElement("button"); downloadBtn.textContent = "Download"; downloadBtn.classList.add("download-btn"); downloadBtn.addEventListener("click", () => { const link = document.createElement("a"); link.href = imgEl.src; link.download = "generated_image.png"; link.click(); }); imgContainer.appendChild(imgEl); imgContainer.appendChild(downloadBtn); chatBox.appendChild(imgContainer); chatBox.scrollTop = chatBox.scrollHeight; saveMessage("Generated image for prompt: " + promptStr, "system"); } catch (err) { console.error("Error generating image:", err); loadingMsg.innerText = "Error generating image"; } } function extractTextFromImage() { document.getElementById("textImageInput").click(); } function processExtractText() { const file = document.getElementById("textImageInput").files[0]; if (file) { const chatBox = document.getElementById("chatBox"); const msgDiv = document.createElement("div"); msgDiv.classList.add("chat-message", "bot-message"); msgDiv.innerHTML = '<div class="spinner"></div>'; chatBox.appendChild(msgDiv); chatBox.scrollTop = chatBox.scrollHeight; const imgUrl = URL.createObjectURL(file); puter.ai.img2txt(imgUrl) .then(text => { msgDiv.innerText = "Extracted Text: " + text; saveMessage("Extracted Text: " + text, "system"); }) .catch(err => { console.error("Error extracting text:", err); msgDiv.innerText = "Error extracting text from image."; }); } } function chatWithGPT4Vision() { document.getElementById("visionImageInput").click(); } function processVisionChat() { const file = document.getElementById("visionImageInput").files[0]; if (file) { const chatBox = document.getElementById("chatBox"); const msgDiv = document.createElement("div"); msgDiv.classList.add("chat-message", "bot-message"); msgDiv.innerHTML = '<div class="spinner"></div>'; chatBox.appendChild(msgDiv); chatBox.scrollTop = chatBox.scrollHeight; const imgUrl = URL.createObjectURL(file); puter.ai.chat("What do you see?", imgUrl) .then(response => { msgDiv.innerText = response; saveMessage(response, "system"); }) .catch(err => { console.error("Error in GPTβ4 Vision chat:", err); msgDiv.innerText = "Error in GPTβ4 Vision chat."; }); } } async function manualSignIn() { await puter.auth.signIn().then((res) => { const chatBox = document.getElementById("chatBox"); const msgDiv = document.createElement("div"); msgDiv.classList.add("chat-message", "bot-message"); msgDiv.innerHTML = "Signed in Successfully"; chatBox.appendChild(msgDiv); chatBox.scrollTop = chatBox.scrollHeight; }); } // ------------------------------- // New Feature: Voice Recognition (using Web Speech API) // ------------------------------- let recognition; let isRecording = false; if ("webkitSpeechRecognition" in window || "SpeechRecognition" in window) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; recognition = new SpeechRecognition(); recognition.continuous = true; recognition.interimResults = true; recognition.lang = "en-US"; recognition.onresult = (event) => { let transcript = ""; for (let i = event.resultIndex; i < event.results.length; i++) { transcript += event.results[i][0].transcript; } document.getElementById("chatInput").value = transcript; }; recognition.onerror = (event) => { console.error("Speech recognition error", event); toggleVoiceRecording(); // stop on error }; } function toggleVoiceRecording() { if (!isRecording) { // Start recording and change voice icon (if desired) if (recognition) { recognition.start(); isRecording = true; document.getElementById("voiceButton").innerText = "βΉοΈ"; } } else { recognition.stop(); isRecording = false; document.getElementById("voiceButton").innerText = "ποΈ"; } } // ------------------------------- // Sidebar & Menu Toggle Functions // ------------------------------- function toggleSidebar() { const sb = document.getElementById("sidebar"); sb.classList.toggle("collapsed"); } function mobileToggleSidebar() { const sb = document.getElementById("sidebar"); if (sb.classList.contains("open")) { sb.classList.remove("open"); } else { sb.classList.add("open"); } } function hideSidebarMobile() { const sb = document.getElementById("sidebar"); if (sb.classList.contains("open")) { sb.classList.remove("open"); } } async function fetchWebData(query) { try { const response = await fetch('fetch_web_data.php?query=' + encodeURIComponent(query)); return await response.text(); } catch (error) { console.error("Error fetching web data:", error); return "Couldn't fetch web data."; } } document.getElementById("chatInput").addEventListener("focus", hideSidebarMobile); function suppressDialog() { setInterval(() => { const dialog = document.querySelector("puter-dialog"); if (dialog) { dialog.remove(); if (!isSignedIn) { autoSignIn(); } } }, 1000); } // Dummy functions for search and reason icons function triggerWebSearch() { setSearchType("web"); alert("Web Search mode activated"); } function triggerReason() { alert("Reason mode activated β you can now ask for detailed explanations."); } window.onload = () => { displayChatHistory(); if (!isSignedIn) { autoSignIn(); } }; window.addEventListener("storage", (evt) => { if (evt.key === "authToken" && evt.newValue === null) { alert("Your session has expired. Please sign in again."); window.location.reload(); } }); </script> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 8.3.24 | Generation time: 0.06 |
proxy
|
phpinfo
|
Settings