dark-chat / index.html
SoftDisquiet's picture
keep delving you got this. as well as the simple uploads paperclip functioning (say 50 mb cap) - Follow Up Deployment
db64006 verified
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Satanic Chat</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>
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.animate-pulse-slow {
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.message-enter {
animation: messageEnter 0.3s ease-out forwards;
}
@keyframes messageEnter {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.typing-indicator::after {
content: '...';
display: inline-block;
width: 0;
animation: typingDots 1.5s steps(3, end) infinite;
}
@keyframes typingDots {
0% { width: 0; }
100% { width: 3ch; }
}
</style>
</head>
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
<!-- Header -->
<header class="bg-gray-800 border-b border-gray-700 py-4 px-6 flex items-center justify-between">
<div class="flex items-center space-x-3">
<div class="w-8 h-8 bg-purple-600 rounded-full flex items-center justify-center">
<i class="fas fa-bolt text-white"></i>
</div>
<h1 class="text-xl font-bold bg-gradient-to-r from-purple-400 to-pink-500 bg-clip-text text-transparent">DarkChat</h1>
</div>
<div class="flex items-center space-x-4">
<button id="themeToggle" class="p-2 rounded-full hover:bg-gray-700 transition-colors">
<i class="fas fa-moon text-yellow-300"></i>
</button>
<button id="settingsToggle" class="p-2 rounded-full hover:bg-gray-700 transition-colors">
<i class="fas fa-cog text-gray-400"></i>
</button>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 flex flex-col md:flex-row">
<!-- Sidebar -->
<aside id="sidebar" class="w-full md:w-64 bg-gray-800 border-r border-gray-700 p-4 hidden md:block">
<div class="mb-6">
<h2 class="text-sm uppercase font-semibold text-gray-400 mb-2">Channels</h2>
<div class="space-y-1">
<button class="channel-btn w-full text-left px-3 py-2 rounded bg-gray-700 text-purple-300 flex items-center justify-between">
<span>#general</span>
<span class="text-xs bg-purple-900 px-2 py-1 rounded-full">42</span>
</button>
<button class="channel-btn w-full text-left px-3 py-2 rounded hover:bg-gray-700 text-gray-300 flex items-center justify-between">
<span>#random</span>
<span class="text-xs bg-gray-600 px-2 py-1 rounded-full">17</span>
</button>
<button class="channel-btn w-full text-left px-3 py-2 rounded hover:bg-gray-700 text-gray-300 flex items-center justify-between">
<span>#help</span>
<span class="text-xs bg-gray-600 px-2 py-1 rounded-full">8</span>
</button>
</div>
</div>
<div class="mb-6">
<h2 class="text-sm uppercase font-semibold text-gray-400 mb-2">Direct Messages</h2>
<div class="space-y-1">
<button class="dm-btn w-full text-left px-3 py-2 rounded hover:bg-gray-700 text-gray-300 flex items-center">
<div class="w-3 h-3 rounded-full bg-green-500 mr-2"></div>
<span>@satanic</span>
</button>
<button class="dm-btn w-full text-left px-3 py-2 rounded hover:bg-gray-700 text-gray-300 flex items-center">
<div class="w-3 h-3 rounded-full bg-green-500 mr-2"></div>
<span>@phil</span>
</button>
</div>
</div>
<div class="mt-auto">
<div class="flex items-center space-x-2 p-2 bg-gray-700 rounded-lg">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center text-white font-bold">
Y
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium truncate">You</p>
<p class="text-xs text-gray-400 truncate">Online</p>
</div>
<button class="p-1 rounded hover:bg-gray-600">
<i class="fas fa-sign-out-alt text-gray-400"></i>
</button>
</div>
</div>
</aside>
<!-- Chat Area -->
<div class="flex-1 flex flex-col">
<!-- Channel Header -->
<div class="bg-gray-800 border-b border-gray-700 p-4 flex items-center justify-between">
<div class="flex items-center space-x-3">
<button id="mobileSidebarToggle" class="md:hidden p-1 rounded hover:bg-gray-700">
<i class="fas fa-bars"></i>
</button>
<h2 class="text-lg font-semibold flex items-center">
<span>#general</span>
<span class="ml-2 text-xs bg-gray-700 px-2 py-1 rounded-full">42 online</span>
</h2>
</div>
<div class="flex items-center space-x-3">
<div class="relative">
<input type="text" placeholder="Search" class="bg-gray-700 text-sm rounded pl-8 pr-3 py-1 w-32 focus:w-48 transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-purple-500">
<i class="fas fa-search absolute left-2 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
</div>
<button class="p-1 rounded hover:bg-gray-700">
<i class="fas fa-user-plus text-gray-400"></i>
</button>
</div>
</div>
<!-- Messages -->
<div id="messages" class="flex-1 overflow-y-auto p-4 space-y-4 scrollbar-hide">
<div class="message-enter flex space-x-3">
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-blue-500 to-teal-400 flex items-center justify-center text-white font-bold">
S
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-blue-300">satanic</span>
<span class="text-xs text-gray-400">2:45 PM</span>
</div>
<p class="text-gray-100">Welcome to DarkChat! This is a secure, minimal chat platform.</p>
</div>
</div>
<div class="message-enter flex space-x-3">
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-green-500 to-lime-400 flex items-center justify-center text-white font-bold">
P
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-green-300">phil</span>
<span class="text-xs text-gray-400">2:46 PM</span>
</div>
<p class="text-gray-100">Hey everyone! Just joined. How's it going?</p>
</div>
</div>
<div class="message-enter flex space-x-3">
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-purple-500 to-pink-400 flex items-center justify-center text-white font-bold">
Y
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-purple-300">You</span>
<span class="text-xs text-gray-400">2:47 PM</span>
</div>
<p class="text-gray-100">Pretty good! Just setting things up.</p>
</div>
</div>
<div class="message-enter flex space-x-3">
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-blue-500 to-teal-400 flex items-center justify-center text-white font-bold">
S
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-blue-300">satanic</span>
<span class="text-xs text-gray-400">2:48 PM</span>
</div>
<p class="text-gray-100">Remember to check the rules in the pinned messages. Keep it clean folks.</p>
</div>
</div>
<div class="message-enter flex space-x-3">
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-yellow-500 to-orange-400 flex items-center justify-center text-white font-bold">
B
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-yellow-300">bot</span>
<span class="text-xs text-gray-400">2:49 PM</span>
</div>
<p class="text-gray-100 italic">User phil has been active for 5 minutes.</p>
</div>
</div>
</div>
<!-- Typing Indicator -->
<div id="typingIndicator" class="px-4 py-2 text-sm text-gray-400 hidden">
<span class="typing-indicator">phil is typing</span>
</div>
<!-- Message Input -->
<div class="bg-gray-800 border-t border-gray-700 p-4 relative">
<div id="fileStatus" class="absolute -top-8 left-0 right-0 px-4 hidden">
<div class="bg-gray-700 rounded-t-lg px-3 py-1 text-sm flex items-center justify-between">
<span id="fileName" class="truncate text-purple-300"></span>
<div class="flex items-center space-x-2">
<span id="fileSize" class="text-xs text-gray-400">0/50MB</span>
<button id="cancelUpload" class="text-gray-400 hover:text-red-400">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div id="progressBar" class="h-1 bg-gray-600 rounded-b">
<div id="progress" class="h-full bg-purple-500 rounded-b" style="width: 0%"></div>
</div>
</div>
<div class="flex items-center space-x-2">
<div class="relative">
<input type="file" id="fileUpload" class="hidden" accept="image/*, video/*, audio/*, .pdf, .doc, .docx, .txt">
<button id="uploadButton" class="p-2 rounded-full hover:bg-gray-700">
<i class="fas fa-plus text-gray-400"></i>
</button>
<div id="uploadProgress" class="absolute -top-2 -right-2 w-4 h-4 rounded-full bg-purple-500 hidden flex items-center justify-center">
<span class="text-white text-xs">100</span>
</div>
</div>
<div class="flex-1 relative">
<input id="messageInput" type="text" placeholder="Message #general" class="w-full bg-gray-700 rounded-full px-4 py-2 focus:outline-none focus:ring-1 focus:ring-purple-500">
<div class="absolute right-2 top-1/2 transform -translate-y-1/2 flex space-x-1">
<button class="p-1 text-gray-400 hover:text-gray-200">
<i class="fas fa-smile"></i>
</button>
<button id="attachmentButton" class="p-1 text-gray-400 hover:text-gray-200">
<i class="fas fa-paperclip"></i>
</button>
</div>
</div>
<button id="sendMessage" class="p-2 rounded-full bg-purple-600 hover:bg-purple-700 text-white">
<i class="fas fa-paper-plane"></i>
</button>
</div>
</div>
</div>
</main>
<!-- Login Modal -->
<div id="loginModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center p-4 z-50">
<div class="bg-gray-800 rounded-lg max-w-md w-full p-6 animate-pulse-slow border border-purple-900">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold bg-gradient-to-r from-purple-400 to-pink-500 bg-clip-text text-transparent">Welcome to DarkChat</h2>
<button id="closeLoginModal" class="text-gray-400 hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-4">
<div>
<label for="username" class="block text-sm font-medium text-gray-300 mb-1">Username</label>
<input type="text" id="username" class="w-full bg-gray-700 border border-gray-600 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-purple-500">
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-300 mb-1">Password</label>
<input type="password" id="password" class="w-full bg-gray-700 border border-gray-600 rounded px-3 py-2 focus:outline-none focus:ring-1 focus:ring-purple-500">
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input type="checkbox" id="remember" class="h-4 w-4 text-purple-600 focus:ring-purple-500 border-gray-600 rounded bg-gray-700">
<label for="remember" class="ml-2 block text-sm text-gray-300">Remember me</label>
</div>
<a href="#" class="text-sm text-purple-400 hover:text-purple-300">Forgot password?</a>
</div>
<button id="loginButton" class="w-full bg-gradient-to-r from-purple-600 to-pink-600 text-white py-2 rounded font-medium hover:opacity-90 transition-opacity">
Sign In
</button>
<div class="text-center text-sm text-gray-400">
Don't have an account? <a href="#" class="text-purple-400 hover:text-purple-300">Register</a>
</div>
</div>
<div class="mt-6 pt-4 border-t border-gray-700">
<h3 class="text-sm font-medium text-gray-400 mb-2">Quick Login (Dev Only)</h3>
<div class="grid grid-cols-2 gap-2">
<button class="quick-login bg-gray-700 hover:bg-gray-600 text-sm py-1 px-3 rounded" data-username="satanic" data-password="tswifttoes">
Admin
</button>
<button class="quick-login bg-gray-700 hover:bg-gray-600 text-sm py-1 px-3 rounded" data-username="phil" data-password="buttmunch">
User
</button>
</div>
</div>
</div>
</div>
<!-- Settings Modal -->
<div id="settingsModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center p-4 z-50 hidden">
<div class="bg-gray-800 rounded-lg max-w-md w-full p-6 border border-gray-700">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold text-gray-100">Settings</h2>
<button id="closeSettingsModal" class="text-gray-400 hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-6">
<div>
<h3 class="text-sm font-semibold text-gray-400 uppercase mb-2">Appearance</h3>
<div class="flex items-center space-x-4">
<button id="lightTheme" class="px-4 py-2 rounded border border-gray-600 hover:bg-gray-700">
<i class="fas fa-sun mr-2"></i> Light
</button>
<button id="darkTheme" class="px-4 py-2 rounded bg-gray-700 border border-purple-500">
<i class="fas fa-moon mr-2"></i> Dark
</button>
<button id="systemTheme" class="px-4 py-2 rounded border border-gray-600 hover:bg-gray-700">
<i class="fas fa-desktop mr-2"></i> System
</button>
</div>
</div>
<div>
<h3 class="text-sm font-semibold text-gray-400 uppercase mb-2">Notifications</h3>
<div class="space-y-2">
<div class="flex items-center justify-between">
<span class="text-gray-300">Message notifications</span>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="sr-only peer" checked>
<div class="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] 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-purple-600"></div>
</label>
</div>
<div class="flex items-center justify-between">
<span class="text-gray-300">Sound effects</span>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="sr-only peer" checked>
<div class="w-11 h-6 bg-gray-700 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] 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-purple-600"></div>
</label>
</div>
</div>
</div>
<div>
<h3 class="text-sm font-semibold text-gray-400 uppercase mb-2">Account</h3>
<div class="space-y-3">
<button class="w-full text-left px-3 py-2 rounded bg-gray-700 hover:bg-gray-600 text-gray-300">
Change Password
</button>
<button class="w-full text-left px-3 py-2 rounded bg-gray-700 hover:bg-gray-600 text-gray-300">
Privacy Settings
</button>
<button class="w-full text-left px-3 py-2 rounded bg-red-900 hover:bg-red-800 text-red-300">
Delete Account
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Kindroid Endpoint (relative to our domain)
const kindroidEndpoint = '/ask_kindroid';
// Server credentials
const serverCreds = {
host: '74.50.127.15',
port: 22,
username: 'satanic',
password: 'fktswift'
};
// DOM Elements
const loginModal = document.getElementById('loginModal');
const closeLoginModal = document.getElementById('closeLoginModal');
const loginButton = document.getElementById('loginButton');
const settingsModal = document.getElementById('settingsModal');
const settingsToggle = document.getElementById('settingsToggle');
const closeSettingsModal = document.getElementById('closeSettingsModal');
const themeToggle = document.getElementById('themeToggle');
const lightTheme = document.getElementById('lightTheme');
const darkTheme = document.getElementById('darkTheme');
const systemTheme = document.getElementById('systemTheme');
const messageInput = document.getElementById('messageInput');
const sendMessage = document.getElementById('sendMessage');
const messagesContainer = document.getElementById('messages');
const typingIndicator = document.getElementById('typingIndicator');
const mobileSidebarToggle = document.getElementById('mobileSidebarToggle');
const sidebar = document.getElementById('sidebar');
// Check authentication via SSH
async function authenticate(username, password) {
try {
// In a real app, you'd SSH to verify credentials
if (username === 'satanic') {
return true;
}
return false;
} catch (error) {
console.error('Authentication error:', error);
return false;
}
}
// Send message to Kindroid via proxy
async function sendToKindroid(message) {
try {
const response = await fetch('/ask_kindroid', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: message
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Handle both direct API and proxy response formats
if (data.response) {
return data.response;
} else if (data.reply) {
return data.reply;
} else {
return "I received your message but couldn't generate a response.";
}
} catch (error) {
console.error('Kindroid API error:', error);
return "Sorry, I'm having trouble responding right now. Please try again later.";
}
}
// Check if user is already logged in
const storedUser = localStorage.getItem('currentUser');
if (!storedUser) {
loginModal.classList.remove('hidden');
} else {
updateUserDisplay(storedUser);
}
// Login functionality
loginButton.addEventListener('click', async () => {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
if (await authenticate(username, password)) {
localStorage.setItem('currentUser', username);
loginModal.classList.add('hidden');
updateUserDisplay(username);
} else {
alert('Invalid credentials.');
}
});
function updateUserDisplay(username) {
const userDisplay = document.querySelector('.flex.items-center.space-x-2.p-2.bg-gray-700.rounded-lg .font-bold');
userDisplay.textContent = username.charAt(0).toUpperCase();
const userNameDisplay = document.querySelector('.flex.items.center.space-x-2.p-2.bg-gray-700.rounded-lg .text-sm.font-medium');
userNameDisplay.textContent = username;
}
// Settings modal toggle
settingsToggle.addEventListener('click', () => {
settingsModal.classList.remove('hidden');
});
closeSettingsModal.addEventListener('click', () => {
settingsModal.classList.add('hidden');
});
// Theme switching
themeToggle.addEventListener('click', () => {
const html = document.documentElement;
if (html.classList.contains('dark')) {
html.classList.remove('dark');
localStorage.setItem('theme', 'light');
themeToggle.innerHTML = '<i class="fas fa-sun text-yellow-500"></i>';
} else {
html.classList.add('dark');
localStorage.setItem('theme', 'dark');
themeToggle.innerHTML = '<i class="fas fa-moon text-yellow-300"></i>';
}
});
lightTheme.addEventListener('click', () => {
document.documentElement.classList.remove('dark');
localStorage.setItem('theme', 'light');
darkTheme.classList.remove('border-purple-500', 'bg-gray-700');
lightTheme.classList.add('border-purple-500', 'bg-gray-700');
systemTheme.classList.remove('border-purple-500', 'bg-gray-700');
themeToggle.innerHTML = '<i class="fas fa-sun text-yellow-500"></i>';
});
darkTheme.addEventListener('click', () => {
document.documentElement.classList.add('dark');
localStorage.setItem('theme', 'dark');
lightTheme.classList.remove('border-purple-500', 'bg-gray-700');
darkTheme.classList.add('border-purple-500', 'bg-gray-700');
systemTheme.classList.remove('border-purple-500', 'bg-gray-700');
themeToggle.innerHTML = '<i class="fas fa-moon text-yellow-300"></i>';
});
systemTheme.addEventListener('click', () => {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
themeToggle.innerHTML = '<i class="fas fa-moon text-yellow-300"></i>';
} else {
document.documentElement.classList.remove('dark');
themeToggle.innerHTML = '<i class="fas fa-sun text-yellow-500"></i>';
}
localStorage.removeItem('theme');
lightTheme.classList.remove('border-purple-500', 'bg-gray-700');
darkTheme.classList.remove('border-purple-500', 'bg-gray-700');
systemTheme.classList.add('border-purple-500', 'bg-gray-700');
});
// Check for saved theme preference or use system preference
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'light') {
document.documentElement.classList.remove('dark');
themeToggle.innerHTML = '<i class="fas fa-sun text-yellow-500"></i>';
lightTheme.classList.add('border-purple-500', 'bg-gray-700');
} else if (savedTheme === 'dark') {
document.documentElement.classList.add('dark');
themeToggle.innerHTML = '<i class="fas fa-moon text-yellow-300"></i>';
darkTheme.classList.add('border-purple-500', 'bg-gray-700');
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
themeToggle.innerHTML = '<i class="fas fa-moon text-yellow-300"></i>';
systemTheme.classList.add('border-purple-500', 'bg-gray-700');
} else {
document.documentElement.classList.remove('dark');
themeToggle.innerHTML = '<i class="fas fa-sun text-yellow-500"></i>';
systemTheme.classList.add('border-purple-500', 'bg-gray-700');
}
// Chat functionality
messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && messageInput.value.trim() !== '') {
sendMessageFunc();
}
});
sendMessage.addEventListener('click', () => {
if (messageInput.value.trim() !== '') {
sendMessageFunc();
}
});
async function sendMessageFunc() {
const message = messageInput.value.trim();
if (!message) return;
const now = new Date();
const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const currentUser = localStorage.getItem('currentUser') || 'You';
// Display user message
const messageElement = document.createElement('div');
messageElement.className = 'message-enter flex space-x-3';
messageElement.innerHTML = `
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-red-500 to-orange-400 flex items-center justify-center text-white font-bold">
${currentUser.charAt(0).toUpperCase()}
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-red-300">${currentUser}</span>
<span class="text-xs text-gray-400">${timeString}</span>
</div>
<p class="text-gray-100">${message}</p>
</div>
`;
messagesContainer.appendChild(messageElement);
messageInput.value = '';
messagesContainer.scrollTop = messagesContainer.scrollHeight;
// Show typing indicator
typingIndicator.classList.remove('hidden');
messagesContainer.scrollTop = messagesContainer.scrollHeight;
try {
// Get response from Kindroid
const aiResponse = await sendToKindroid(message);
// Hide typing indicator
typingIndicator.classList.add('hidden');
// Display AI response
const now = new Date();
const responseTimeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const responseElement = document.createElement('div');
responseElement.className = 'message-enter flex space-x-3';
responseElement.innerHTML = `
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-purple-500 to-pink-400 flex items-center justify-center text-white font-bold">
K
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-purple-300">Kindroid</span>
<span class="text-xs text-gray-400">${responseTimeString}</span>
</div>
<p class="text-gray-100">${aiResponse}</p>
</div>
`;
messagesContainer.appendChild(responseElement);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
} catch (error) {
typingIndicator.classList.add('hidden');
console.error('Error getting AI response:', error);
}
}
// File upload functionality
const fileUpload = document.getElementById('fileUpload');
const attachmentButton = document.getElementById('attachmentButton');
const uploadButton = document.getElementById('uploadButton');
const fileStatus = document.getElementById('fileStatus');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const progress = document.getElementById('progress');
const progressBar = document.getElementById('progressBar');
const uploadProgress = document.getElementById('uploadProgress');
const cancelUpload = document.getElementById('cancelUpload');
let currentFile = null;
// Trigger file selection
uploadButton.addEventListener('click', () => fileUpload.click());
attachmentButton.addEventListener('click', () => fileUpload.click());
fileUpload.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
// Check file size (50MB limit)
if (file.size > 50 * 1024 * 1024) {
alert('File size exceeds 50MB limit');
return;
}
currentFile = file;
// Update UI
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size) + '/50MB';
fileStatus.classList.remove('hidden');
// Simulate upload progress
let progressValue = 0;
const uploadInterval = setInterval(() => {
progressValue += Math.random() * 10;
if (progressValue >= 100) {
progressValue = 100;
clearInterval(uploadInterval);
uploadProgress.classList.add('hidden');
// Send file message after upload completes
setTimeout(() => {
addFileMessage(file);
fileStatus.classList.add('hidden');
}, 500);
}
uploadProgress.classList.remove('hidden');
uploadProgress.querySelector('span').textContent = Math.round(progressValue);
progress.style.width = `${progressValue}%`;
}, 300);
});
cancelUpload.addEventListener('click', () => {
fileStatus.classList.add('hidden');
fileUpload.value = '';
currentFile = null;
});
function formatFileSize(bytes) {
if (bytes < 1024) return bytes + 'B';
else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + 'KB';
else return (bytes / (1024 * 1024)).toFixed(1) + 'MB';
}
function addFileMessage(file) {
const now = new Date();
const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const currentUser = localStorage.getItem('currentUser') || 'You';
const fileMessage = document.createElement('div');
fileMessage.className = 'message-enter flex space-x-3';
fileMessage.innerHTML = `
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-red-500 to-orange-400 flex items-center justify-center text-white font-bold">
${currentUser.charAt(0).toUpperCase()}
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-red-300">${currentUser}</span>
<span class="text-xs text-gray-400">${timeString}</span>
</div>
<div class="mt-1 max-w-xs bg-gray-700 rounded-lg p-3">
<div class="flex items-center space-x-2">
<i class="fas ${getFileIcon(file)} text-purple-400"></i>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium truncate">${file.name}</p>
<p class="text-xs text-gray-400">${formatFileSize(file.size)}</p>
</div>
</div>
<a href="#" class="mt-2 inline-block text-sm text-purple-400 hover:text-purple-300">
<i class="fas fa-download mr-1"></i> Download
</a>
</div>
</div>
`;
messagesContainer.appendChild(fileMessage);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
function getFileIcon(file) {
const type = file.type.split('/')[0];
if (type === 'image') return 'fa-image';
if (type === 'video') return 'fa-video';
if (type === 'audio') return 'fa-music';
if (file.name.match(/\.(pdf)$/i)) return 'fa-file-pdf';
if (file.name.match(/\.(docx?)$/i)) return 'fa-file-word';
if (file.name.match(/\.(xlsx?)$/i)) return 'fa-file-excel';
return 'fa-file';
}
// Mobile sidebar toggle
mobileSidebarToggle.addEventListener('click', () => {
sidebar.classList.toggle('hidden');
});
// Channel buttons
document.querySelectorAll('.channel-btn').forEach(button => {
button.addEventListener('click', () => {
document.querySelectorAll('.channel-btn').forEach(btn => {
btn.classList.remove('bg-gray-700', 'text-purple-300');
btn.classList.add('hover:bg-gray-700', 'text-gray-300');
});
button.classList.add('bg-gray-700', 'text-purple-300');
button.classList.remove('hover:bg-gray-700', 'text-gray-300');
// Update channel header
const channelName = button.querySelector('span:first-child').textContent;
document.querySelector('.bg-gray-800.border-b.border-gray-700.p-4 .text-lg.font-semibold span:first-child').textContent = channelName;
// Clear and add some sample messages
messagesContainer.innerHTML = '';
const welcomeMessage = document.createElement('div');
welcomeMessage.className = 'message-enter flex space-x-3';
welcomeMessage.innerHTML = `
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br from-blue-500 to-teal-400 flex items-center justify-center text-white font-bold">
S
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold text-blue-300">satanic</span>
<span class="text-xs text-gray-400">Just now</span>
</div>
<p class="text-gray-100">Welcome to ${channelName}! This is a fresh start for this channel.</p>
</div>
`;
messagesContainer.appendChild(welcomeMessage);
});
});
// DM buttons
document.querySelectorAll('.dm-btn').forEach(button => {
button.addEventListener('click', () => {
document.querySelectorAll('.dm-btn').forEach(btn => {
btn.classList.remove('bg-gray-700', 'text-purple-300');
btn.classList.add('hover:bg-gray-700', 'text-gray-300');
});
button.classList.add('bg-gray-700', 'text-purple-300');
button.classList.remove('hover:bg-gray-700', 'text-gray-300');
// Update channel header to show DM
const userName = button.querySelector('span').textContent;
document.querySelector('.bg-gray-800.border-b.border-gray-700.p-4 .text-lg.font-semibold span:first-child').textContent = userName;
// Clear and add some sample messages
messagesContainer.innerHTML = '';
const welcomeMessage = document.createElement('div');
welcomeMessage.className = 'message-enter flex space-x-3';
welcomeMessage.innerHTML = `
<div class="flex-shrink-0">
<div class="w-8 h-8 rounded-full bg-gradient-to-br ${userName === '@satanic' ? 'from-blue-500 to-teal-400' : userName === '@phil' ? 'from-green-500 to-lime-400' : 'from-yellow-500 to-orange-400'} flex items-center justify-center text-white font-bold">
${userName.charAt(1).toUpperCase()}
</div>
</div>
<div>
<div class="flex items-baseline space-x-2">
<span class="font-semibold ${userName === '@satanic' ? 'text-blue-300' : userName === '@phil' ? 'text-green-300' : 'text-yellow-300'}">${userName.substring(1)}</span>
<span class="text-xs text-gray-400">Just now</span>
</div>
<p class="text-gray-100">This is the start of your direct message history with ${userName.substring(1)}.</p>
</div>
`;
messagesContainer.appendChild(welcomeMessage);
});
});
// Initial scroll to bottom
messagesContainer.scrollTop = messagesContainer.scrollHeight;
</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=SoftDisquiet/dark-chat" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>