mirror of
https://github.com/umutcamliyurt/Amnezichat.git
synced 2025-05-05 13:20:47 +01:00
206 lines
6.9 KiB
HTML
206 lines
6.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<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>
|
|
|
|
<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>
|
|
|
|
<!-- Media Modal -->
|
|
<div id="mediaModal" onclick="closeMediaModal()">
|
|
<span class="close-btn" onclick="closeMediaModal(); event.stopPropagation();">×</span>
|
|
</div>
|
|
|
|
<script>
|
|
let profilePicBase64 = localStorage.getItem("profilePic") || "";
|
|
let lastNotifiedMessages = new Set();
|
|
|
|
function showNotification(message) {
|
|
if (!lastNotifiedMessages.has(message) && Notification.permission === "granted") {
|
|
new Notification("New Message", {
|
|
body: message.replace(/<strong>|<\/strong>/g, '')
|
|
});
|
|
lastNotifiedMessages.add(message);
|
|
}
|
|
}
|
|
|
|
function requestNotificationPermission() {
|
|
if (Notification.permission !== "granted") {
|
|
Notification.requestPermission();
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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>`;
|
|
}
|
|
}
|
|
|
|
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>
|
|
</body>
|
|
</html>
|