2025-02-08 22:29:25 +03:00
<!DOCTYPE html>
< html lang = "en" >
< head >
2025-04-14 14:57:01 +03:00
< meta charset = "UTF-8" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" / >
< title > Amnezichat< / title >
< link rel = "stylesheet" href = "/static/styles.css" / >
< script src = "/static/purify.min.js" > < / script >
< / head >
< body onload = "fetchMessages(); requestNotificationPermission(); setInterval(fetchMessages, 3000);" >
< div class = "container" >
< div id = "messages" > < / div >
< div class = "input-container" >
< input type = "text" id = "messageInput" placeholder = "Type a message..." autocomplete = "off" / >
< button onclick = "sendMessage()" > Send< / button >
< button onclick = "toggleSettings()" > Settings< / button >
< / div >
< / div >
2025-02-21 22:42:28 +03:00
2025-04-14 14:57:01 +03:00
< div id = "settings" >
< div class = "settings-content" >
< h2 > Settings< / h2 >
< input type = "file" accept = "image/*" id = "profilePicInput" style = "display:none;" onchange = "handleProfilePicChange(event)" / >
< button onclick = "document.getElementById('profilePicInput').click()" > Choose Profile Picture< / button >
< input type = "file" accept = "image/*,video/*" id = "mediaInput" style = "display:none;" onchange = "handleMediaChange(event)" / >
< button onclick = "document.getElementById('mediaInput').click()" > Send Media< / button >
< button onclick = "toggleTheme()" > Toggle Light/Dark Mode< / button >
< button onclick = "closeSettings()" > Close< / button >
< / div >
< / div >
2025-02-08 22:29:25 +03:00
2025-04-14 14:57:01 +03:00
<!-- Media Modal -->
< div id = "mediaModal" onclick = "closeMediaModal()" >
< span class = "close-btn" onclick = "closeMediaModal(); event.stopPropagation();" > × < / span >
< / div >
2025-02-08 22:29:25 +03:00
2025-04-14 14:57:01 +03:00
< script >
let profilePicBase64 = localStorage.getItem("profilePic") || "";
let lastNotifiedMessages = new Set();
2025-02-08 22:29:25 +03:00
2025-04-14 14:57:01 +03:00
function showNotification(message) {
if (!lastNotifiedMessages.has(message) & & Notification.permission === "granted") {
new Notification("New Message", {
body: message.replace(/< strong > |< \/strong>/g, '')
});
lastNotifiedMessages.add(message);
}
}
2025-02-08 22:29:25 +03:00
2025-04-14 14:57:01 +03:00
function requestNotificationPermission() {
if (Notification.permission !== "granted") {
Notification.requestPermission();
}
}
2025-02-08 22:29:25 +03:00
2025-04-14 14:57:01 +03:00
function handleProfilePicChange(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
profilePicBase64 = reader.result;
localStorage.setItem("profilePic", profilePicBase64);
};
reader.readAsDataURL(file);
}
}
2025-02-08 22:29:25 +03:00
2025-04-14 14:57:01 +03:00
function handleMediaChange(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onloadend = async () => {
const mediaBase64 = reader.result;
let message = `< pfp > ${profilePicBase64}< / pfp > < media > ${mediaBase64}< / media > `;
await fetch('/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
});
fetchMessages();
};
reader.readAsDataURL(file);
}
}
async function fetchMessages() {
const res = await fetch('/messages');
const messages = await res.json();
const messagesDiv = document.getElementById('messages');
const base64Img = /^data:image\/(png|jpeg|jpg|gif|svg\+xml);base64,/;
const base64Vid = /^data:video\/(mp4|webm|ogg);base64,/;
messagesDiv.innerHTML = messages.map(msg => {
const pfpMatch = msg.match(/< pfp > (.*?)< \/pfp>/);
const mediaMatch = msg.match(/< media > (.*?)< \/media>/);
const messageText = msg.replace(/< pfp > .*?< \/pfp>/, '').replace(/< media > .*?< \/media>/, '').trim();
const profilePicSrc = pfpMatch & & base64Img.test(pfpMatch[1])
? pfpMatch[1]
: '/static/default_pfp.jpg';
const profilePic = `< img src = "${profilePicSrc}" class = "profile-pic" alt = "Profile Picture" > `;
let media = "";
if (mediaMatch) {
const src = mediaMatch[1];
if (base64Img.test(src)) {
media = `< img src = "${src}" class = "media-img" alt = "Media" onclick = "openMediaModal('${src}', false)" > `;
} else if (base64Vid.test(src)) {
media = `< video class = "media-video" controls onclick = "openMediaModal('${src}', true)" > < source src = "${src}" type = "video/mp4" > Your browser does not support video.< / video > `;
}
2025-02-08 22:29:25 +03:00
}
2025-04-14 14:57:01 +03:00
showNotification(messageText || 'New media message');
return `
< div class = "message-row" >
${profilePic}
< div class = "message-bubble" >
${messageText ? `< p > ${DOMPurify.sanitize(messageText)}< / p > ` : ''}
${media}
< / div >
< / div > `;
}).join('');
messagesDiv.scrollTo({ top: messagesDiv.scrollHeight, behavior: 'smooth' });
}
async function sendMessage() {
const input = document.getElementById('messageInput');
const msg = input.value.trim();
// Skip sending if message is truly empty
if (!msg) return;
const sanitizedMsg = DOMPurify.sanitize(msg);
const message = `< pfp > ${profilePicBase64}< / pfp > ${sanitizedMsg}`;
await fetch('/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message })
});
input.value = '';
fetchMessages();
}
function toggleSettings() {
const modal = document.getElementById('settings');
modal.style.display = modal.style.display === 'flex' ? 'none' : 'flex';
}
function closeSettings() {
document.getElementById('settings').style.display = 'none';
}
function toggleTheme() {
document.body.classList.toggle('light-theme');
}
function openMediaModal(src, isVideo = false) {
const modal = document.getElementById("mediaModal");
modal.innerHTML = `< span class = "close-btn" onclick = "closeMediaModal(); event.stopPropagation();" > × < / span > `;
if (isVideo) {
const video = document.createElement('video');
video.controls = true;
video.src = src;
video.autoplay = true;
video.style.maxWidth = '90%';
video.style.maxHeight = '90%';
video.style.borderRadius = '10px';
modal.appendChild(video);
} else {
const img = document.createElement('img');
img.src = src;
img.style.maxWidth = '90%';
img.style.maxHeight = '90%';
img.style.borderRadius = '10px';
modal.appendChild(img);
}
modal.style.display = "flex";
}
function closeMediaModal() {
const modal = document.getElementById("mediaModal");
modal.style.display = "none";
modal.innerHTML = `< span class = "close-btn" onclick = "closeMediaModal(); event.stopPropagation();" > × < / span > `;
}
document.addEventListener("DOMContentLoaded", () => {
const savedPic = localStorage.getItem("profilePic");
if (savedPic) {
profilePicBase64 = savedPic;
}
});
< / script >
2025-02-08 22:29:25 +03:00
< / body >
< / html >