imagex / index.html
peterquill193's picture
Update index.html
4f31fdd verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ImageX - Advanced Image Generator</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">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#6366f1',
secondary: '#8b5cf6',
dark: '#1e293b',
light: '#f8fafc'
},
boxShadow: {
'neumorphic': '8px 8px 16px #d1d9e6, -8px -8px 16px #ffffff',
'neumorphic-inset': 'inset 4px 4px 8px #d1d9e6, inset -4px -4px 8px #ffffff',
'neumorphic-sm': '4px 4px 8px #d1d9e6, -4px -4px 8px #ffffff'
}
}
}
}
</script>
<style>
body {
background-color: #f1f5f9;
font-family: 'Inter', sans-serif;
min-height: 100vh;
}
.neumorphic {
border-radius: 16px;
background: linear-gradient(145deg, #ffffff, #e6e6e6);
box-shadow: 8px 8px 16px #d1d9e6, -8px -8px 16px #ffffff;
}
.neumorphic-inset {
border-radius: 16px;
background: linear-gradient(145deg, #e6e6e6, #ffffff);
box-shadow: inset 4px 4px 8px #d1d9e6, inset -4px -4px 8px #ffffff;
}
.neumorphic-btn {
border-radius: 12px;
background: linear-gradient(145deg, #ffffff, #e6e6e6);
box-shadow: 4px 4px 8px #d1d9e6, -4px -4px 8px #ffffff;
transition: all 0.3s ease;
}
.neumorphic-btn:hover {
box-shadow: 2px 2px 4px #d1d9e6, -2px -2px 4px #ffffff;
}
.neumorphic-btn:active {
box-shadow: inset 2px 2px 4px #d1d9e6, inset -2px -2px 4px #ffffff;
}
.loading-dots {
display: inline-flex;
align-items: center;
}
.loading-dots span {
width: 8px;
height: 8px;
margin: 0 3px;
background-color: #6366f1;
border-radius: 50%;
display: inline-block;
animation: bounce 1.4s infinite ease-in-out both;
}
.loading-dots span:nth-child(1) {
animation-delay: -0.32s;
}
.loading-dots span:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes bounce {
0%, 80%, 100% {
transform: scale(0);
} 40% {
transform: scale(1);
}
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background: #c7d2fe;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: #a5b4fc;
}
/* Fade-in animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
/* Pulse animation for generate button */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s infinite;
}
</style>
<!-- Pixel Code for https://kriztech.in/analytics/ -->
<script defer src="https://kriztech.in/analytics/pixel/t5geuVzC1fN2oM1G"></script>
<!-- END Pixel Code -->
</head>
<body class="bg-gray-100 text-gray-800">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold mb-2 text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary">
ImageX
</h1>
<p class="text-lg text-gray-600">Advanced AI Image Generator with Neomorphic UI</p>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Panel - Controls -->
<div class="lg:col-span-1">
<div class="neumorphic p-6 rounded-2xl mb-6">
<h2 class="text-xl font-semibold mb-4 text-gray-700">Image Settings</h2>
<!-- Prompt Input -->
<div class="mb-6">
<label for="prompt" class="block text-sm font-medium text-gray-600 mb-2">Describe your image</label>
<div class="neumorphic-inset rounded-xl p-1">
<textarea
id="prompt"
rows="4"
class="w-full bg-transparent border-none focus:ring-0 focus:outline-none px-4 py-3 text-gray-700 placeholder-gray-400 resize-none"
placeholder="A futuristic cityscape at sunset with flying cars..."
></textarea>
</div>
<div class="flex justify-between mt-2 text-xs text-gray-500">
<span id="charCount">0/500</span>
<button id="enhancePrompt" class="text-primary hover:text-secondary transition">
<i class="fas fa-magic mr-1"></i> Enhance Prompt
</button>
</div>
</div>
<!-- Style Selection -->
<div class="mb-6">
<label class="block text-sm font-medium text-gray-600 mb-2">Art Style</label>
<div class="grid grid-cols-3 gap-2">
<button class="style-option neumorphic-btn py-2 px-3 rounded-lg text-xs flex flex-col items-center" data-style="realistic">
<i class="fas fa-user text-primary mb-1"></i>
<span>Realistic</span>
</button>
<button class="style-option neumorphic-btn py-2 px-3 rounded-lg text-xs flex flex-col items-center" data-style="fantasy">
<i class="fas fa-dragon text-purple-500 mb-1"></i>
<span>Fantasy</span>
</button>
<button class="style-option neumorphic-btn py-2 px-3 rounded-lg text-xs flex flex-col items-center" data-style="anime">
<i class="fas fa-moon text-pink-500 mb-1"></i>
<span>Anime</span>
</button>
<button class="style-option neumorphic-btn py-2 px-3 rounded-lg text-xs flex flex-col items-center" data-style="cyberpunk">
<i class="fas fa-robot text-blue-500 mb-1"></i>
<span>Cyberpunk</span>
</button>
<button class="style-option neumorphic-btn py-2 px-3 rounded-lg text-xs flex flex-col items-center" data-style="watercolor">
<i class="fas fa-paint-brush text-green-500 mb-1"></i>
<span>Watercolor</span>
</button>
<button class="style-option neumorphic-btn py-2 px-3 rounded-lg text-xs flex flex-col items-center" data-style="pixel">
<i class="fas fa-gamepad text-yellow-500 mb-1"></i>
<span>Pixel Art</span>
</button>
</div>
</div>
<!-- Advanced Options -->
<div class="mb-6">
<div class="flex justify-between items-center mb-2">
<label class="text-sm font-medium text-gray-600">Advanced Options</label>
<button id="toggleAdvanced" class="text-xs text-primary">
<i class="fas fa-chevron-down mr-1"></i> Show
</button>
</div>
<div id="advancedOptions" class="hidden space-y-4 pt-2">
<!-- Image Size -->
<div>
<label class="block text-xs font-medium text-gray-500 mb-1">Image Size</label>
<div class="grid grid-cols-3 gap-2">
<button class="size-option neumorphic-btn py-1 px-2 rounded-lg text-xs" data-width="512" data-height="512">
512x512
</button>
<button class="size-option neumorphic-btn py-1 px-2 rounded-lg text-xs" data-width="768" data-height="512">
768x512
</button>
<button class="size-option neumorphic-btn py-1 px-2 rounded-lg text-xs" data-width="1024" data-height="1024">
1024x1024
</button>
</div>
</div>
<!-- Guidance Scale -->
<div>
<label class="block text-xs font-medium text-gray-500 mb-1">Creativity Level</label>
<input type="range" id="guidanceScale" min="1" max="20" value="7.5" step="0.5" class="w-full">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>Precise</span>
<span id="guidanceValue">7.5</span>
<span>Creative</span>
</div>
</div>
<!-- Seed Input -->
<div>
<label for="seed" class="block text-xs font-medium text-gray-500 mb-1">Seed (for reproducibility)</label>
<div class="flex">
<input
type="number"
id="seed"
class="neumorphic-inset w-full bg-transparent border-none focus:ring-0 focus:outline-none px-3 py-2 text-gray-700 rounded-l-lg"
placeholder="Random"
>
<button id="randomSeed" class="neumorphic-btn px-3 rounded-r-lg text-gray-600">
<i class="fas fa-dice"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Generate Button -->
<button id="generateBtn" class="w-full neumorphic-btn py-3 px-6 rounded-xl bg-gradient-to-r from-primary to-secondary text-white font-medium text-lg shadow-lg hover:shadow-xl transition-all duration-300 pulse">
<i class="fas fa-sparkles mr-2"></i> Generate Image
</button>
<!-- History Button -->
<div class="mt-4 flex justify-between">
<button id="showHistory" class="neumorphic-btn py-2 px-4 rounded-lg text-sm text-gray-700">
<i class="fas fa-history mr-2"></i> History
</button>
<button id="saveSettings" class="neumorphic-btn py-2 px-4 rounded-lg text-sm text-gray-700">
<i class="fas fa-save mr-2"></i> Save Preset
</button>
</div>
</div>
<!-- Tips Section -->
<div class="neumorphic p-6 rounded-2xl">
<h3 class="font-medium text-gray-700 mb-3 flex items-center">
<i class="fas fa-lightbulb text-yellow-500 mr-2"></i> Prompt Tips
</h3>
<ul class="text-sm text-gray-600 space-y-2">
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2 text-xs"></i>
<span>Be specific about subjects, colors, and composition</span>
</li>
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2 text-xs"></i>
<span>Include art style (e.g., "digital art", "oil painting")</span>
</li>
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2 text-xs"></i>
<span>Add lighting details (e.g., "dramatic lighting", "soft glow")</span>
</li>
<li class="flex items-start">
<i class="fas fa-check-circle text-green-500 mt-1 mr-2 text-xs"></i>
<span>Specify perspective (e.g., "close-up", "aerial view")</span>
</li>
</ul>
</div>
</div>
<!-- Right Panel - Results -->
<div class="lg:col-span-2">
<!-- Generated Image Display -->
<div class="neumorphic rounded-2xl p-6 mb-6 min-h-[512px] flex flex-col">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-700">Generated Image</h2>
<div id="generationInfo" class="text-sm text-gray-500 hidden">
<span id="modelInfo">SDXL</span><span id="timeInfo">5.2s</span>
</div>
</div>
<div id="imageContainer" class="flex-1 flex items-center justify-center bg-gray-50 rounded-xl overflow-hidden relative">
<div id="placeholder" class="text-center p-8">
<div class="mx-auto w-20 h-20 bg-gradient-to-r from-primary to-secondary rounded-full flex items-center justify-center text-white mb-4">
<i class="fas fa-image text-3xl"></i>
</div>
<h3 class="text-lg font-medium text-gray-700 mb-2">Your AI-generated image will appear here</h3>
<p class="text-gray-500 text-sm">Enter a prompt and click "Generate Image" to create your masterpiece</p>
</div>
<div id="loadingIndicator" class="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
<div class="text-center p-6 neumorphic rounded-xl">
<div class="loading-dots mb-4">
<span></span>
<span></span>
<span></span>
</div>
<p class="text-white font-medium">Generating your image...</p>
<p class="text-gray-300 text-sm mt-1">This usually takes 10-30 seconds</p>
</div>
</div>
<img id="generatedImage" class="w-full h-auto max-h-[70vh] object-contain hidden rounded-lg" alt="Generated image">
</div>
<!-- Image Actions -->
<div id="imageActions" class="mt-4 flex flex-wrap gap-2 hidden">
<button id="downloadBtn" class="neumorphic-btn py-2 px-4 rounded-lg flex items-center text-sm">
<i class="fas fa-download mr-2"></i> Download
</button>
<button id="upscaleBtn" class="neumorphic-btn py-2 px-4 rounded-lg flex items-center text-sm">
<i class="fas fa-expand mr-2"></i> Upscale
</button>
<button id="variationsBtn" class="neumorphic-btn py-2 px-4 rounded-lg flex items-center text-sm">
<i class="fas fa-copy mr-2"></i> Variations
</button>
<button id="shareBtn" class="neumorphic-btn py-2 px-4 rounded-lg flex items-center text-sm">
<i class="fas fa-share-alt mr-2"></i> Share
</button>
<button id="remixBtn" class="neumorphic-btn py-2 px-4 rounded-lg flex items-center text-sm ml-auto">
<i class="fas fa-random mr-2"></i> Remix
</button>
</div>
</div>
<!-- History Panel (Hidden by default) -->
<div id="historyPanel" class="neumorphic rounded-2xl p-6 hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-700">Generation History</h2>
<button id="closeHistory" class="neumorphic-btn p-2 rounded-lg">
<i class="fas fa-times"></i>
</button>
</div>
<div id="historyGrid" class="grid grid-cols-2 md:grid-cols-3 gap-3">
<!-- History items will be added here dynamically -->
<div class="text-center py-8 text-gray-400">
<i class="fas fa-box-open text-3xl mb-2"></i>
<p>Your generation history will appear here</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div id="toast" class="fixed bottom-4 right-4 neumorphic p-4 rounded-xl shadow-lg transform translate-y-10 opacity-0 transition-all duration-300 hidden">
<div class="flex items-center">
<div id="toastIcon" class="mr-3"></div>
<div>
<p id="toastMessage" class="text-sm font-medium"></p>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const promptInput = document.getElementById('prompt');
const charCount = document.getElementById('charCount');
const enhancePromptBtn = document.getElementById('enhancePrompt');
const styleOptions = document.querySelectorAll('.style-option');
const sizeOptions = document.querySelectorAll('.size-option');
const guidanceScale = document.getElementById('guidanceScale');
const guidanceValue = document.getElementById('guidanceValue');
const seedInput = document.getElementById('seed');
const randomSeedBtn = document.getElementById('randomSeed');
const generateBtn = document.getElementById('generateBtn');
const toggleAdvancedBtn = document.getElementById('toggleAdvanced');
const advancedOptions = document.getElementById('advancedOptions');
const showHistoryBtn = document.getElementById('showHistory');
const closeHistoryBtn = document.getElementById('closeHistory');
const historyPanel = document.getElementById('historyPanel');
const imageContainer = document.getElementById('imageContainer');
const placeholder = document.getElementById('placeholder');
const loadingIndicator = document.getElementById('loadingIndicator');
const generatedImage = document.getElementById('generatedImage');
const imageActions = document.getElementById('imageActions');
const downloadBtn = document.getElementById('downloadBtn');
const upscaleBtn = document.getElementById('upscaleBtn');
const variationsBtn = document.getElementById('variationsBtn');
const shareBtn = document.getElementById('shareBtn');
const remixBtn = document.getElementById('remixBtn');
const generationInfo = document.getElementById('generationInfo');
const modelInfo = document.getElementById('modelInfo');
const timeInfo = document.getElementById('timeInfo');
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toastMessage');
const toastIcon = document.getElementById('toastIcon');
const saveSettingsBtn = document.getElementById('saveSettings');
// State variables
let currentSettings = {
style: 'realistic',
width: 512,
height: 512,
guidance: 7.5,
seed: null,
prompt: ''
};
let generationHistory = JSON.parse(localStorage.getItem('generationHistory')) || [];
// Initialize
updateCharCount();
setActiveStyle('realistic');
setActiveSize(512, 512);
// Event Listeners
promptInput.addEventListener('input', updateCharCount);
enhancePromptBtn.addEventListener('click', enhancePrompt);
styleOptions.forEach(option => {
option.addEventListener('click', function() {
setActiveStyle(this.dataset.style);
});
});
sizeOptions.forEach(option => {
option.addEventListener('click', function() {
setActiveSize(parseInt(this.dataset.width), parseInt(this.dataset.height));
});
});
guidanceScale.addEventListener('input', function() {
guidanceValue.textContent = this.value;
currentSettings.guidance = parseFloat(this.value);
});
randomSeedBtn.addEventListener('click', function() {
const randomSeed = Math.floor(Math.random() * 1000000);
seedInput.value = randomSeed;
currentSettings.seed = randomSeed;
});
toggleAdvancedBtn.addEventListener('click', function() {
advancedOptions.classList.toggle('hidden');
const icon = this.querySelector('i');
if (advancedOptions.classList.contains('hidden')) {
this.innerHTML = '<i class="fas fa-chevron-down mr-1"></i> Show';
} else {
this.innerHTML = '<i class="fas fa-chevron-up mr-1"></i> Hide';
}
});
generateBtn.addEventListener('click', generateImage);
showHistoryBtn.addEventListener('click', function() {
historyPanel.classList.remove('hidden');
loadHistory();
});
closeHistoryBtn.addEventListener('click', function() {
historyPanel.classList.add('hidden');
});
downloadBtn.addEventListener('click', downloadImage);
upscaleBtn.addEventListener('click', function() {
showToast('Upscaling feature coming soon!', 'info');
});
variationsBtn.addEventListener('click', function() {
showToast('Variations feature coming soon!', 'info');
});
shareBtn.addEventListener('click', function() {
if (navigator.share) {
navigator.share({
title: 'Check out this AI-generated image!',
text: 'I created this using NeoGen AI Image Generator',
url: generatedImage.src
}).catch(err => {
showToast('Sharing failed: ' + err, 'error');
});
} else {
// Fallback for browsers that don't support Web Share API
copyToClipboard(generatedImage.src);
showToast('Image URL copied to clipboard!', 'success');
}
});
remixBtn.addEventListener('click', function() {
generateImage();
});
saveSettingsBtn.addEventListener('click', function() {
const presetName = prompt('Enter a name for this preset:');
if (presetName) {
const presets = JSON.parse(localStorage.getItem('presets')) || [];
presets.push({
name: presetName,
settings: currentSettings
});
localStorage.setItem('presets', JSON.stringify(presets));
showToast(`Preset "${presetName}" saved!`, 'success');
}
});
// Functions
function updateCharCount() {
const count = promptInput.value.length;
charCount.textContent = `${count}/500`;
currentSettings.prompt = promptInput.value;
}
function setActiveStyle(style) {
styleOptions.forEach(option => {
option.classList.remove('bg-primary', 'text-white');
option.classList.add('neumorphic-btn');
});
const activeOption = document.querySelector(`.style-option[data-style="${style}"]`);
activeOption.classList.remove('neumorphic-btn');
activeOption.classList.add('bg-primary', 'text-white');
currentSettings.style = style;
}
function setActiveSize(width, height) {
sizeOptions.forEach(option => {
option.classList.remove('bg-primary', 'text-white');
option.classList.add('neumorphic-btn');
});
const activeOption = document.querySelector(`.size-option[data-width="${width}"]`);
activeOption.classList.remove('neumorphic-btn');
activeOption.classList.add('bg-primary', 'text-white');
currentSettings.width = width;
currentSettings.height = height;
}
function enhancePrompt() {
if (!promptInput.value.trim()) {
showToast('Please enter a prompt first', 'error');
return;
}
// Simulate AI enhancement (in a real app, this would call an API)
showToast('Enhancing your prompt...', 'info');
setTimeout(() => {
const enhanced = enhancePromptAI(promptInput.value);
promptInput.value = enhanced;
updateCharCount();
showToast('Prompt enhanced!', 'success');
}, 1000);
}
function enhancePromptAI(prompt) {
// This is a mock enhancement - a real implementation would use an AI service
const enhancements = [
"highly detailed, intricate, digital painting",
"trending on artstation, 4k resolution",
"cinematic lighting, ultra-detailed",
"concept art, smooth, sharp focus"
];
const randomEnhancement = enhancements[Math.floor(Math.random() * enhancements.length)];
return `${prompt}, ${randomEnhancement}`;
}
async function generateImage() {
if (!promptInput.value.trim()) {
showToast('Please enter a prompt', 'error');
return;
}
// Update current settings
currentSettings.prompt = promptInput.value;
currentSettings.seed = seedInput.value || Math.floor(Math.random() * 1000000);
// Show loading state
placeholder.classList.add('hidden');
loadingIndicator.classList.remove('hidden');
generatedImage.classList.add('hidden');
imageActions.classList.add('hidden');
try {
const startTime = Date.now();
// Construct the API URL for Pollinations AI
const apiUrl = `https://image.pollinations.ai/prompt/${encodeURIComponent(
`${currentSettings.prompt}, ${currentSettings.style} style, high quality, high resolution`
)}?width=${currentSettings.width}&height=${currentSettings.height}&seed=${currentSettings.seed}&nologo=true`;
// Fetch the image
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error('Failed to generate image');
}
const blob = await response.blob();
const imageUrl = URL.createObjectURL(blob);
// Display the image
generatedImage.src = imageUrl;
generatedImage.onload = function() {
loadingIndicator.classList.add('hidden');
generatedImage.classList.remove('hidden');
imageActions.classList.remove('hidden');
generationInfo.classList.remove('hidden');
// Calculate generation time
const endTime = Date.now();
const generationTime = ((endTime - startTime) / 1000).toFixed(1);
timeInfo.textContent = `${generationTime}s`;
// Add to history
addToHistory({
prompt: currentSettings.prompt,
imageUrl: imageUrl,
settings: {...currentSettings},
timestamp: new Date().toISOString()
});
};
} catch (error) {
console.error('Error generating image:', error);
loadingIndicator.classList.add('hidden');
placeholder.classList.remove('hidden');
showToast('Failed to generate image. Please try again.', 'error');
}
}
function addToHistory(item) {
generationHistory.unshift(item);
if (generationHistory.length > 12) {
generationHistory = generationHistory.slice(0, 12);
}
localStorage.setItem('generationHistory', JSON.stringify(generationHistory));
if (!historyPanel.classList.contains('hidden')) {
loadHistory();
}
}
function loadHistory() {
const historyGrid = document.getElementById('historyGrid');
historyGrid.innerHTML = '';
if (generationHistory.length === 0) {
historyGrid.innerHTML = `
<div class="col-span-3 text-center py-8 text-gray-400">
<i class="fas fa-box-open text-3xl mb-2"></i>
<p>Your generation history is empty</p>
</div>
`;
return;
}
generationHistory.forEach((item, index) => {
const historyItem = document.createElement('div');
historyItem.className = 'neumorphic-btn rounded-lg overflow-hidden cursor-pointer group';
historyItem.innerHTML = `
<div class="relative aspect-square">
<img src="${item.imageUrl}" alt="Generated image" class="w-full h-full object-cover">
<div class="absolute inset-0 bg-black bg-opacity-60 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center p-2">
<p class="text-white text-xs text-center">${item.prompt.substring(0, 60)}${item.prompt.length > 60 ? '...' : ''}</p>
</div>
</div>
<div class="p-2">
<p class="text-xs text-gray-500 truncate">${new Date(item.timestamp).toLocaleString()}</p>
</div>
`;
historyItem.addEventListener('click', function() {
generatedImage.src = item.imageUrl;
generatedImage.classList.remove('hidden');
placeholder.classList.add('hidden');
imageActions.classList.remove('hidden');
historyPanel.classList.add('hidden');
// Update settings to match history item
promptInput.value = item.settings.prompt;
updateCharCount();
setActiveStyle(item.settings.style || 'realistic');
setActiveSize(item.settings.width || 512, item.settings.height || 512);
guidanceScale.value = item.settings.guidance || 7.5;
guidanceValue.textContent = item.settings.guidance || 7.5;
seedInput.value = item.settings.seed || '';
showToast('History item loaded', 'success');
});
historyGrid.appendChild(historyItem);
});
}
function downloadImage() {
if (!generatedImage.src) return;
const link = document.createElement('a');
link.href = generatedImage.src;
link.download = `ai-image-${Date.now()}.jpg`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToast('Image downloaded!', 'success');
}
function copyToClipboard(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}
function showToast(message, type) {
// Set message and icon based on type
toastMessage.textContent = message;
let iconClass, bgColor;
switch(type) {
case 'success':
iconClass = 'fas fa-check-circle text-green-500';
bgColor = 'bg-green-100';
break;
case 'error':
iconClass = 'fas fa-exclamation-circle text-red-500';
bgColor = 'bg-red-100';
break;
case 'info':
iconClass = 'fas fa-info-circle text-blue-500';
bgColor = 'bg-blue-100';
break;
default:
iconClass = 'fas fa-info-circle text-primary';
bgColor = 'bg-primary';
}
// Update toast
toastIcon.className = iconClass + ' text-xl';
toast.className = `fixed bottom-4 right-4 neumorphic p-4 rounded-xl shadow-lg transform translate-y-10 opacity-0 transition-all duration-300 ${bgColor}`;
// Show toast
setTimeout(() => {
toast.classList.remove('hidden');
setTimeout(() => {
toast.classList.remove('translate-y-10');
toast.classList.remove('opacity-0');
}, 10);
}, 10);
// Hide after 3 seconds
setTimeout(() => {
toast.classList.add('translate-y-10');
toast.classList.add('opacity-0');
setTimeout(() => {
toast.classList.add('hidden');
}, 300);
}, 3000);
}
});
</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=peterquill193/imagex" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>