Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Zalamati</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
body { | |
font-family: 'Inter', sans-serif; | |
background-color: #0a0a0a; | |
color: #f3f4f6; | |
} | |
.gradient-bg { | |
background: linear-gradient(135deg, #1e1e2e 0%, #111827 100%); | |
} | |
.message-animation { | |
animation: fadeIn 0.3s ease-out; | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; transform: translateY(10px); } | |
to { opacity: 1; transform: translateY(0); } | |
} | |
.typing-indicator::after { | |
content: '...'; | |
animation: typing 1.5s infinite; | |
} | |
@keyframes typing { | |
0% { content: '.'; } | |
33% { content: '..'; } | |
66% { content: '...'; } | |
} | |
/* Custom scrollbar */ | |
::-webkit-scrollbar { | |
width: 6px; | |
} | |
::-webkit-scrollbar-track { | |
background: #1f2937; | |
} | |
::-webkit-scrollbar-thumb { | |
background: #4b5563; | |
border-radius: 3px; | |
} | |
::-webkit-scrollbar-thumb:hover { | |
background: #6b7280; | |
} | |
/* File upload styling */ | |
.file-upload { | |
position: relative; | |
overflow: hidden; | |
} | |
.file-upload input { | |
position: absolute; | |
top: 0; | |
right: 0; | |
margin: 0; | |
padding: 0; | |
font-size: 20px; | |
cursor: pointer; | |
opacity: 0; | |
height: 100%; | |
width: 100%; | |
} | |
/* Modal styling */ | |
.modal { | |
display: none; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0, 0, 0, 0.7); | |
z-index: 1000; | |
justify-content: center; | |
align-items: center; | |
} | |
.modal-content { | |
background-color: #1f2937; | |
border-radius: 0.5rem; | |
width: 90%; | |
max-width: 500px; | |
max-height: 90vh; | |
overflow-y: auto; | |
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); | |
} | |
/* Settings panel */ | |
.settings-panel { | |
display: none; | |
position: absolute; | |
right: 1rem; | |
top: 4rem; | |
background-color: #1f2937; | |
border-radius: 0.5rem; | |
width: 300px; | |
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5); | |
z-index: 100; | |
border: 1px solid #374151; | |
} | |
</style> | |
</head> | |
<body class="h-screen flex flex-col"> | |
<!-- Header --> | |
<header class="gradient-bg border-b border-gray-800 py-4 px-6 flex items-center justify-between"> | |
<div class="flex items-center space-x-3"> | |
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center"> | |
<i class="fas fa-robot text-white"></i> | |
</div> | |
<h1 class="text-xl font-semibold">Zalamati</h1> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<button id="settingsButton" class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-cog"></i> | |
</button> | |
<button id="themeToggle" class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-moon"></i> | |
</button> | |
<button class="bg-gradient-to-r from-purple-600 to-blue-500 text-white px-4 py-1.5 rounded-full text-sm font-medium hover:opacity-90 transition-opacity"> | |
Upgrade | |
</button> | |
</div> | |
<!-- Settings Panel --> | |
<div id="settingsPanel" class="settings-panel p-4"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="font-medium text-lg">Settings</h3> | |
<button id="closeSettings" class="text-gray-400 hover:text-white"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
<div class="space-y-4"> | |
<div> | |
<label class="block text-sm font-medium text-gray-300 mb-1">Theme</label> | |
<select id="themeSelect" class="w-full bg-gray-800 border border-gray-700 text-gray-300 rounded-md py-2 px-3 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500"> | |
<option value="dark">Dark</option> | |
<option value="light">Light</option> | |
<option value="system">System</option> | |
</select> | |
</div> | |
<div> | |
<label class="block text-sm font-medium text-gray-300 mb-1">Default Model</label> | |
<select id="defaultModelSelect" class="w-full bg-gray-800 border border-gray-700 text-gray-300 rounded-md py-2 px-3 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500"> | |
<option>ZalamatiPro (GPT-4)</option> | |
<option>Zalamati Ultra (GPT-4 Turbo)</option> | |
<option>Zalamati Basic (GPT-3.5)</option> | |
<option>Claude 3 Opus</option> | |
<option>Gemini Pro</option> | |
</select> | |
</div> | |
<div class="flex items-center justify-between"> | |
<span class="text-sm font-medium text-gray-300">Enable Web Search</span> | |
<label class="relative inline-flex items-center cursor-pointer"> | |
<input type="checkbox" id="webSearchToggle" checked class="sr-only peer"> | |
<div class="w-11 h-6 bg-gray-700 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-500"></div> | |
</label> | |
</div> | |
<div class="flex items-center justify-between"> | |
<span class="text-sm font-medium text-gray-300">Enable Voice Input</span> | |
<label class="relative inline-flex items-center cursor-pointer"> | |
<input type="checkbox" id="voiceInputToggle" checked class="sr-only peer"> | |
<div class="w-11 h-6 bg-gray-700 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-500"></div> | |
</label> | |
</div> | |
<div class="pt-2 border-t border-gray-700"> | |
<button class="w-full bg-gray-800 hover:bg-gray-700 text-gray-300 py-2 rounded-md text-sm font-medium transition-colors"> | |
<i class="fas fa-sign-out-alt mr-2"></i> Logout | |
</button> | |
</div> | |
</div> | |
</div> | |
</header> | |
<!-- Main Content --> | |
<div class="flex flex-1 overflow-hidden"> | |
<!-- Sidebar --> | |
<aside class="w-64 gradient-bg border-r border-gray-800 hidden md:block overflow-y-auto"> | |
<div class="p-4"> | |
<button id="newChatButton" class="w-full bg-gradient-to-r from-purple-600 to-blue-500 text-white py-2.5 rounded-lg font-medium flex items-center justify-center space-x-2 mb-4"> | |
<i class="fas fa-plus"></i> | |
<span>New Chat</span> | |
</button> | |
<div class="space-y-1"> | |
<div class="text-gray-400 text-xs uppercase font-medium px-2 py-1">Recent Chats</div> | |
<button class="w-full text-left px-3 py-2 rounded-lg bg-gray-800 text-white flex items-center justify-between"> | |
<span class="truncate">How to build a React app</span> | |
<i class="fas fa-ellipsis-h text-gray-400"></i> | |
</button> | |
<button class="w-full text-left px-3 py-2 rounded-lg hover:bg-gray-800 text-gray-300 flex items-center justify-between"> | |
<span class="truncate">JavaScript best practices</span> | |
<i class="fas fa-ellipsis-h text-gray-400"></i> | |
</button> | |
<button class="w-full text-left px-3 py-2 rounded-lg hover:bg-gray-800 text-gray-300 flex items-center justify-between"> | |
<span class="truncate">Python data analysis</span> | |
<i class="fas fa-ellipsis-h text-gray-400"></i> | |
</button> | |
</div> | |
<div class="mt-6 space-y-1"> | |
<div class="text-gray-400 text-xs uppercase font-medium px-2 py-1">Collections</div> | |
<button class="w-full text-left px-3 py-2 rounded-lg hover:bg-gray-800 text-gray-300 flex items-center space-x-2"> | |
<i class="fas fa-code text-blue-400"></i> | |
<span>Programming</span> | |
</button> | |
<button class="w-full text-left px-3 py-2 rounded-lg hover:bg-gray-800 text-gray-300 flex items-center space-x-2"> | |
<i class="fas fa-chart-line text-green-400"></i> | |
<span>Data Science</span> | |
</button> | |
<button class="w-full text-left px-3 py-2 rounded-lg hover:bg-gray-800 text-gray-300 flex items-center space-x-2"> | |
<i class="fas fa-briefcase text-purple-400"></i> | |
<span>Business</span> | |
</button> | |
</div> | |
<div class="mt-6 p-3 bg-gray-900 rounded-lg"> | |
<div class="flex items-center space-x-3"> | |
<div class="w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center"> | |
<i class="fas fa-user text-gray-400"></i> | |
</div> | |
<div> | |
<div class="font-medium">Free Plan</div> | |
<div class="text-xs text-gray-400">5/20 messages left</div> | |
</div> | |
</div> | |
<div class="mt-3 h-1.5 w-full bg-gray-700 rounded-full overflow-hidden"> | |
<div class="h-full bg-gradient-to-r from-purple-500 to-blue-500 rounded-full" style="width: 25%"></div> | |
</div> | |
</div> | |
</div> | |
</aside> | |
<!-- Chat Area --> | |
<main class="flex-1 flex flex-col overflow-hidden"> | |
<!-- Model Selector --> | |
<div class="gradient-bg border-b border-gray-800 py-2 px-4 flex items-center justify-between"> | |
<div class="flex items-center space-x-2"> | |
<div class="relative"> | |
<select id="modelSelect" class="bg-gray-800 border border-gray-700 text-gray-300 rounded-md py-1.5 pl-3 pr-8 text-sm appearance-none focus:outline-none focus:ring-1 focus:ring-purple-500"> | |
<option>Zalamati Pro (GPT-4)</option> | |
<option>Zalamati Ultra (GPT-4 Turbo)</option> | |
<option>Zalamati Basic (GPT-3.5)</option> | |
<option>Claude 3 Opus</option> | |
<option>Gemini Pro</option> | |
</select> | |
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-400"> | |
<i class="fas fa-chevron-down text-xs"></i> | |
</div> | |
</div> | |
<div class="flex items-center text-xs text-gray-400"> | |
<i class="fas fa-plug mr-1"></i> | |
<span>Internet Access</span> | |
<label class="relative inline-flex items-center cursor-pointer ml-2"> | |
<input type="checkbox" id="internetAccessToggle" checked class="sr-only peer"> | |
<div class="w-7 h-4 bg-gray-700 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-3 after:w-3 after:transition-all peer-checked:bg-blue-500"></div> | |
</label> | |
</div> | |
</div> | |
<div class="flex items-center space-x-3"> | |
<button id="clearChatButton" class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-trash-alt"></i> | |
</button> | |
<button id="shareChatButton" class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-share-alt"></i> | |
</button> | |
</div> | |
</div> | |
<!-- Messages Container --> | |
<div id="messages" class="flex-1 overflow-y-auto p-4 space-y-6"> | |
<!-- Welcome Message --> | |
<div class="message-animation max-w-3xl mx-auto bg-gray-800 rounded-xl p-4"> | |
<div class="flex items-start space-x-3"> | |
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center shrink-0"> | |
<i class="fas fa-robot text-white text-sm"></i> | |
</div> | |
<div class="flex-1"> | |
<div class="font-medium text-gray-100">Zalamati</div> | |
<div class="mt-1 text-gray-300"> | |
<p>Hello! I'm Zalamati, your intelligent assistant. I can help with:</p> | |
<ul class="list-disc pl-5 mt-2 space-y-1"> | |
<li>Answering questions with web search</li> | |
<li>Analyzing uploaded documents</li> | |
<li>Code generation and debugging</li> | |
<li>Creative writing and brainstorming</li> | |
</ul> | |
<p class="mt-2">How can I assist you today?</p> | |
</div> | |
<div class="mt-3 flex flex-wrap gap-2"> | |
<button class="sample-question text-xs bg-gray-700 hover:bg-gray-600 text-gray-200 px-3 py-1 rounded-full">Explain quantum computing</button> | |
<button class="sample-question text-xs bg-gray-700 hover:bg-gray-600 text-gray-200 px-3 py-1 rounded-full">Write a Python script</button> | |
<button class="sample-question text-xs bg-gray-700 hover:bg-gray-600 text-gray-200 px-3 py-1 rounded-full">Help me study for exam</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Input Area --> | |
<div class="gradient-bg border-t border-gray-800 p-4"> | |
<div class="max-w-3xl mx-auto"> | |
<div class="relative"> | |
<textarea id="userInput" rows="1" class="w-full bg-gray-800 border border-gray-700 rounded-xl py-3 pl-4 pr-12 text-gray-200 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-purple-500 resize-none" placeholder="Message Zalamati..."></textarea> | |
<div class="absolute right-3 bottom-3 flex items-center space-x-2"> | |
<button class="file-upload text-gray-400 hover:text-gray-200 p-1 rounded-full"> | |
<i class="fas fa-paperclip"></i> | |
<input type="file" id="fileUpload" class="hidden"> | |
</button> | |
<button id="voiceButton" class="text-gray-400 hover:text-gray-200 p-1 rounded-full"> | |
<i class="fas fa-microphone"></i> | |
</button> | |
<button id="sendButton" class="bg-gradient-to-r from-purple-600 to-blue-500 text-white p-2 rounded-full hover:opacity-90 transition-opacity"> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
</div> | |
<div class="mt-2 text-xs text-gray-500 text-center"> | |
Zalamati can make mistakes. Consider checking important information. | |
</div> | |
</div> | |
</div> | |
</main> | |
</div> | |
<!-- Mobile Bottom Navigation --> | |
<div class="md:hidden gradient-bg border-t border-gray-800 flex justify-around py-3"> | |
<button class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-home text-xl"></i> | |
</button> | |
<button class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-comment text-xl"></i> | |
</button> | |
<button id="mobileUploadButton" class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-file-upload text-xl"></i> | |
</button> | |
<button id="mobileSettingsButton" class="text-gray-400 hover:text-white transition-colors"> | |
<i class="fas fa-cog text-xl"></i> | |
</button> | |
</div> | |
<!-- File Upload Modal --> | |
<div id="fileUploadModal" class="modal"> | |
<div class="modal-content p-6"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="font-medium text-lg">Upload File</h3> | |
<button id="closeUploadModal" class="text-gray-400 hover:text-white"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
<div class="border-2 border-dashed border-gray-600 rounded-lg p-8 text-center mb-4"> | |
<i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i> | |
<p class="text-gray-300 mb-2">Drag & drop files here</p> | |
<p class="text-xs text-gray-500 mb-4">or</p> | |
<label for="modalFileUpload" class="bg-gray-800 hover:bg-gray-700 text-gray-300 py-2 px-4 rounded-md cursor-pointer"> | |
Select Files | |
</label> | |
<input type="file" id="modalFileUpload" class="hidden"> | |
</div> | |
<div class="text-xs text-gray-500"> | |
Supported formats: PDF, TXT, DOCX, PPTX, XLSX (Max 25MB) | |
</div> | |
</div> | |
</div> | |
<!-- Share Modal --> | |
<div id="shareModal" class="modal"> | |
<div class="modal-content p-6"> | |
<div class="flex justify-between items-center mb-4"> | |
<h3 class="font-medium text-lg">Share Chat</h3> | |
<button id="closeShareModal" class="text-gray-400 hover:text-white"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
<div class="mb-4"> | |
<label class="block text-sm font-medium text-gray-300 mb-1">Share Link</label> | |
<div class="flex"> | |
<input type="text" id="shareLink" class="flex-1 bg-gray-800 border border-gray-700 text-gray-300 rounded-l-md py-2 px-3 text-sm focus:outline-none" value="https://Zalamatiai.com/share/abc123" readonly> | |
<button id="copyShareLink" class="bg-gray-700 hover:bg-gray-600 text-gray-300 py-2 px-3 rounded-r-md text-sm"> | |
<i class="fas fa-copy"></i> | |
</button> | |
</div> | |
</div> | |
<div class="mb-4"> | |
<label class="block text-sm font-medium text-gray-300 mb-1">Permissions</label> | |
<select class="w-full bg-gray-800 border border-gray-700 text-gray-300 rounded-md py-2 px-3 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500"> | |
<option>Anyone with the link</option> | |
<option>Only people you specify</option> | |
<option>Only me</option> | |
</select> | |
</div> | |
<div class="flex space-x-2"> | |
<button class="flex-1 bg-gray-800 hover:bg-gray-700 text-gray-300 py-2 rounded-md text-sm font-medium"> | |
<i class="fab fa-whatsapp mr-2"></i> WhatsApp | |
</button> | |
<button class="flex-1 bg-gray-800 hover:bg-gray-700 text-gray-300 py-2 rounded-md text-sm font-medium"> | |
<i class="fab fa-telegram mr-2"></i> Telegram | |
</button> | |
<button class="flex-1 bg-gray-800 hover:bg-gray-700 text-gray-300 py-2 rounded-md text-sm font-medium"> | |
<i class="fas fa-envelope mr-2"></i> Email | |
</button> | |
</div> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// DOM Elements | |
const userInput = document.getElementById('userInput'); | |
const sendButton = document.getElementById('sendButton'); | |
const messagesContainer = document.getElementById('messages'); | |
const voiceButton = document.getElementById('voiceButton'); | |
const fileUpload = document.getElementById('fileUpload'); | |
const settingsButton = document.getElementById('settingsButton'); | |
const settingsPanel = document.getElementById('settingsPanel'); | |
const closeSettings = document.getElementById('closeSettings'); | |
const themeToggle = document.getElementById('themeToggle'); | |
const newChatButton = document.getElementById('newChatButton'); | |
const clearChatButton = document.getElementById('clearChatButton'); | |
const shareChatButton = document.getElementById('shareChatButton'); | |
const modelSelect = document.getElementById('modelSelect'); | |
const internetAccessToggle = document.getElementById('internetAccessToggle'); | |
const mobileUploadButton = document.getElementById('mobileUploadButton'); | |
const mobileSettingsButton = document.getElementById('mobileSettingsButton'); | |
const fileUploadModal = document.getElementById('fileUploadModal'); | |
const closeUploadModal = document.getElementById('closeUploadModal'); | |
const modalFileUpload = document.getElementById('modalFileUpload'); | |
const shareModal = document.getElementById('shareModal'); | |
const closeShareModal = document.getElementById('closeShareModal'); | |
const copyShareLink = document.getElementById('copyShareLink'); | |
// Initialize chat history | |
let chatHistory = []; | |
// Auto-resize textarea | |
userInput.addEventListener('input', function() { | |
this.style.height = 'auto'; | |
this.style.height = (this.scrollHeight) + 'px'; | |
}); | |
// Send message on Enter (Shift+Enter for new line) | |
userInput.addEventListener('keydown', function(e) { | |
if (e.key === 'Enter' && !e.shiftKey) { | |
e.preventDefault(); | |
sendMessage(); | |
} | |
}); | |
// Send button click | |
sendButton.addEventListener('click', sendMessage); | |
// Sample question buttons | |
document.querySelectorAll('.sample-question').forEach(button => { | |
button.addEventListener('click', function() { | |
userInput.value = this.textContent; | |
userInput.dispatchEvent(new Event('input')); | |
sendMessage(); | |
}); | |
}); | |
// Settings panel toggle | |
settingsButton.addEventListener('click', function() { | |
settingsPanel.style.display = settingsPanel.style.display === 'block' ? 'none' : 'block'; | |
}); | |
mobileSettingsButton.addEventListener('click', function() { | |
settingsPanel.style.display = settingsPanel.style.display === 'block' ? 'none' : 'block'; | |
}); | |
closeSettings.addEventListener('click', function() { | |
settingsPanel.style.display = 'none'; | |
}); | |
// Close settings when clicking outside | |
document.addEventListener('click', function(event) { | |
if (!settingsPanel.contains(event.target) && event.target !== settingsButton && event.target !== mobileSettingsButton) { | |
settingsPanel.style.display = 'none'; | |
} | |
}); | |
// Theme toggle | |
themeToggle.addEventListener('click', function() { | |
document.body.classList.toggle('light-theme'); | |
const icon = themeToggle.querySelector('i'); | |
if (document.body.classList.contains('light-theme')) { | |
icon.classList.remove('fa-moon'); | |
icon.classList.add('fa-sun'); | |
} else { | |
icon.classList.remove('fa-sun'); | |
icon.classList.add('fa-moon'); | |
} | |
}); | |
// New chat button | |
newChatButton.addEventListener('click', function() { | |
if (messagesContainer.children.length > 1 || chatHistory.length > 0) { | |
if (confirm('Start a new chat? Your current chat will be saved.')) { | |
clearChat(); | |
} | |
} | |
}); | |
// Clear chat button | |
clearChatButton.addEventListener('click', function() { | |
if (messagesContainer.children.length > 1 || chatHistory.length > 0) { | |
if (confirm('Are you sure you want to clear this chat?')) { | |
clearChat(); | |
} | |
} | |
}); | |
// Share chat button | |
shareChatButton.addEventListener('click', function() { | |
shareModal.style.display = 'flex'; | |
}); | |
closeShareModal.addEventListener('click', function() { | |
shareModal.style.display = 'none'; | |
}); | |
copyShareLink.addEventListener('click', function() { | |
const shareLink = document.getElementById('shareLink'); | |
shareLink.select(); | |
document.execCommand('copy'); | |
const originalText = this.innerHTML; | |
this.innerHTML = '<i class="fas fa-check"></i> Copied!'; | |
setTimeout(() => { | |
this.innerHTML = originalText; | |
}, 2000); | |
}); | |
// File upload handling | |
fileUpload.addEventListener('change', handleFileUpload); | |
mobileUploadButton.addEventListener('click', function() { | |
fileUploadModal.style.display = 'flex'; | |
}); | |
modalFileUpload.addEventListener('change', function() { | |
handleFileUpload({ target: { files: this.files } }); | |
fileUploadModal.style.display = 'none'; | |
}); | |
closeUploadModal.addEventListener('click', function() { | |
fileUploadModal.style.display = 'none'; | |
}); | |
// Close modals when clicking outside | |
window.addEventListener('click', function(event) { | |
if (event.target === fileUploadModal) { | |
fileUploadModal.style.display = 'none'; | |
} | |
if (event.target === shareModal) { | |
shareModal.style.display = 'none'; | |
} | |
}); | |
// Model select change | |
modelSelect.addEventListener('change', function() { | |
console.log('Model changed to:', this.value); | |
}); | |
// Internet access toggle | |
internetAccessToggle.addEventListener('change', function() { | |
console.log('Internet access:', this.checked ? 'Enabled' : 'Disabled'); | |
}); | |
// Voice recognition | |
let recognition; | |
let isListening = false; | |
voiceButton.addEventListener('click', toggleVoiceRecognition); | |
// Functions | |
function sendMessage() { | |
const message = userInput.value.trim(); | |
if (message === '') return; | |
// Add user message | |
addMessage(message, 'user'); | |
chatHistory.push({ role: 'user', content: message }); | |
userInput.value = ''; | |
userInput.style.height = 'auto'; | |
// Show typing indicator | |
const typingIndicator = document.createElement('div'); | |
typingIndicator.className = 'max-w-3xl mx-auto bg-gray-800 rounded-xl p-4'; | |
typingIndicator.innerHTML = ` | |
<div class="flex items-start space-x-3"> | |
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-600 to-blue-500 flex items-center justify-center shrink-0"> | |
<i class="fas fa-robot text-white text-sm"></i> | |
</div> | |
<div class="flex-1"> | |
<div class="font-medium text-gray-100">Zalamati</div> | |
<div class="mt-1 text-gray-300 typing-indicator">Thinking</div> | |
</div> | |
</div> | |
`; | |
messagesContainer.appendChild(typingIndicator); | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
// Simulate AI response after delay | |
setTimeout(() => { | |
messagesContainer.removeChild(typingIndicator); | |
// Get selected model | |
const selectedModel = modelSelect.value; | |
// Generate response based on model and message | |
let response; | |
if (message.toLowerCase().includes('hello') || message.toLowerCase().includes('hi')) { | |
response = `Hello! I'm Zalamati (${selectedModel}). How can I assist you today?`; | |
} else if (message.toLowerCase().includes('thank')) { | |
response = "You're welcome! Is there anything else I can help you with?"; | |
} else if (message.toLowerCase().includes('code') || message.toLowerCase().includes('program')) { | |
response = generateCodeResponse(message, selectedModel); | |
} else { | |
response = generateGeneralResponse(message, selectedModel); | |
} | |
// Add AI response | |
addMessage(response, 'ai'); | |
chatHistory.push({ role: 'assistant', content: response }); | |
}, 1500 + Math.random() * 2000); | |
} | |
function addMessage(content, sender) { | |
const messageDiv = document.createElement('div'); | |
messageDiv.className = 'message-animation max-w-3xl mx-auto ' + | |
(sender === 'user' ? 'ml-auto bg-gradient-to-r from-purple-600 to-blue-500' : 'bg-gray-800') + | |
' rounded-xl p-4'; | |
messageDiv.innerHTML = ` | |
<div class="flex items-start space-x-3"> | |
<div class="w-8 h-8 rounded-full ${sender === 'user' ? 'bg-gray-100' : 'bg-gradient-to-r from-purple-600 to-blue-500'} flex items-center justify-center shrink-0"> | |
<i class="fas ${sender === 'user' ? 'fa-user text-gray-800' : 'fa-robot text-white text-sm'}"></i> | |
</div> | |
<div class="flex-1"> | |
<div class="font-medium ${sender === 'user' ? 'text-white' : 'text-gray-100'}">${sender === 'user' ? 'You' : 'Zalamati'}</div> | |
<div class="mt-1 ${sender === 'user' ? 'text-white' : 'text-gray-300'}"> | |
${sender === 'user' ? content : content.replace(/\n/g, '<br>')} | |
</div> | |
${sender === 'ai' ? ` | |
<div class="mt-3 flex items-center space-x-4 text-xs text-gray-400"> | |
<button class="feedback-btn flex items-center space-x-1 hover:text-gray-200" data-feedback="helpful"> | |
<i class="fas fa-thumbs-up"></i> | |
<span>Helpful</span> | |
</button> | |
<button class="feedback-btn flex items-center space-x-1 hover:text-gray-200" data-feedback="not-helpful"> | |
<i class="fas fa-thumbs-down"></i> | |
<span>Not Helpful</span> | |
</button> | |
<button class="regenerate-btn flex items-center space-x-1 hover:text-gray-200"> | |
<i class="fas fa-redo"></i> | |
<span>Regenerate</span> | |
</button> | |
</div> | |
` : ''} | |
</div> | |
</div> | |
`; | |
messagesContainer.appendChild(messageDiv); | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
// Add event listeners for feedback buttons | |
if (sender === 'ai') { | |
messageDiv.querySelectorAll('.feedback-btn').forEach(btn => { | |
btn.addEventListener('click', function() { | |
const feedback = this.getAttribute('data-feedback'); | |
console.log('Feedback:', feedback); | |
this.innerHTML = `<i class="fas fa-${feedback === 'helpful' ? 'check' : 'times'}"></i> ${feedback === 'helpful' ? 'Thanks!' : 'Sorry!'}`; | |
}); | |
}); | |
messageDiv.querySelector('.regenerate-btn').addEventListener('click', function() { | |
const lastUserMessage = chatHistory[chatHistory.length - 2].content; | |
userInput.value = lastUserMessage; | |
userInput.dispatchEvent(new Event('input')); | |
sendMessage(); | |
}); | |
} | |
} | |
function clearChat() { | |
// Keep only the welcome message | |
while (messagesContainer.children.length > 1) { | |
messagesContainer.removeChild(messagesContainer.lastChild); | |
} | |
chatHistory = []; | |
} | |
function toggleVoiceRecognition() { | |
if (!('webkitSpeechRecognition' in window)) { | |
alert('Your browser does not support speech recognition. Try Chrome or Edge.'); | |
return; | |
} | |
if (!isListening) { | |
startVoiceRecognition(); | |
} else { | |
stopVoiceRecognition(); | |
} | |
} | |
function startVoiceRecognition() { | |
recognition = new webkitSpeechRecognition(); | |
recognition.continuous = false; | |
recognition.interimResults = false; | |
recognition.onstart = function() { | |
isListening = true; | |
voiceButton.innerHTML = '<i class="fas fa-microphone-slash"></i>'; | |
voiceButton.classList.remove('text-gray-400', 'hover:text-gray-200'); | |
voiceButton.classList.add('text-red-400'); | |
}; | |
recognition.onresult = function(event) { | |
const transcript = event.results[0][0].transcript; | |
userInput.value = transcript; | |
userInput.dispatchEvent(new Event('input')); | |
}; | |
recognition.onerror = function(event) { | |
console.error('Speech recognition error', event.error); | |
stopVoiceRecognition(); | |
}; | |
recognition.onend = function() { | |
stopVoiceRecognition(); | |
}; | |
recognition.start(); | |
} | |
function stopVoiceRecognition() { | |
if (recognition) { | |
recognition.stop(); | |
} | |
isListening = false; | |
voiceButton.innerHTML = '<i class="fas fa-microphone"></i>'; | |
voiceButton.classList.remove('text-red-400'); | |
voiceButton.classList.add('text-gray-400', 'hover:text-gray-200'); | |
} | |
function handleFileUpload(event) { | |
const file = event.target.files[0]; | |
if (!file) return; | |
// Check file size (25MB max) | |
if (file.size > 25 * 1024 * 1024) { | |
alert('File size exceeds 25MB limit'); | |
return; | |
} | |
// Check file type | |
const allowedTypes = ['application/pdf', 'text/plain', | |
'application/vnd.openxmlformats-officedocument.wordprocessingml.document', | |
'application/vnd.openxmlformats-officedocument.presentationml.presentation', | |
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']; | |
if (!allowedTypes.includes(file.type)) { | |
alert('File type not supported'); | |
return; | |
} | |
// Simulate file processing | |
addMessage(`Processing file: ${file.name} (${(file.size / 1024).toFixed(1)} KB)`, 'user'); | |
chatHistory.push({ role: 'user', content: `[File: ${file.name}]` }); | |
setTimeout(() => { | |
let response; | |
if (file.type === 'application/pdf') { | |
response = `I've analyzed the PDF file "${file.name}". It appears to be ${file.size > 1024 * 1024 ? 'a large' : 'a'} document. ` + | |
'I can summarize its content or answer questions about it. What would you like to know?'; | |
} else if (file.type === 'text/plain') { | |
response = `I've processed the text file "${file.name}". It contains plain text data. ` + | |
'I can analyze, summarize, or extract information from it. How can I help?'; | |
} else { | |
response = `I've analyzed the ${file.type.split('.').pop().toUpperCase()} file "${file.name}". ` + | |
'I can extract data, summarize content, or answer questions about this document. What would you like me to do?'; | |
} | |
addMessage(response, 'ai'); | |
chatHistory.push({ role: 'assistant', content: response }); | |
}, 2000); | |
} | |
function generateCodeResponse(message, model) { | |
const languages = ['Python', 'JavaScript', 'Java', 'C++', 'C#', 'Go', 'Rust', 'TypeScript']; | |
const frameworks = ['React', 'Vue', 'Angular', 'Django', 'Flask', 'Spring', '.NET']; | |
const randomLang = languages[Math.floor(Math.random() * languages.length)]; | |
const randomFramework = frameworks[Math.floor(Math.random() * frameworks.length)]; | |
const responses = [ | |
`Here's a ${randomLang} code example based on your request about "${message}":\n\n` + | |
`\`\`\`${randomLang.toLowerCase()}\n// ${randomLang} code example\nfunction example() {\n console.log("Hello from ${model}!");\n}\n\`\`\``, | |
`For "${message}", here's how you might implement it in ${randomFramework}:\n\n` + | |
`\`\`\`javascript\n// ${randomFramework} component\nclass Example extends React.Component {\n render() {\n return <div>Hello from ${model}</div>;\n }\n}\n\`\`\``, | |
`Based on your question about "${message}", here's a solution:\n\n` + | |
`\`\`\`python\n# ${randomLang} solution\ndef solution():\n return "This is a sample answer from ${model}"\n\`\`\`` | |
]; | |
return responses[Math.floor(Math.random() * responses.length)]; | |
} | |
function generateGeneralResponse(message, model) { | |
const responses = [ | |
`I've analyzed your question about "${message}". Using ${model}, here's what I found...`, | |
`That's an interesting question! With ${model}, I can tell you that...`, | |
`Based on my knowledge and ${model}'s capabilities, here's the answer to your question about "${message}"...`, | |
`I understand you're asking about "${message}". Using ${model}, here's a detailed explanation...` | |
]; | |
return responses[Math.floor(Math.random() * responses.length)] + | |
"\n\nThis is a simulated response. In a real implementation, this would be generated by the AI model you selected."; | |
} | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=PetraAI/zalamati-deepsite" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |