index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Amnezichat</title> 7 <link rel="stylesheet" href="/static/styles.css"> 8 <script src="/static/purify.min.js"></script> 9 <script> 10 let profilePicBase64 = ""; 11 12 // Handle profile picture upload 13 function handleProfilePicChange(event) { 14 const file = event.target.files[0]; 15 if (file) { 16 const reader = new FileReader(); 17 reader.onloadend = function () { 18 profilePicBase64 = reader.result; 19 }; 20 reader.readAsDataURL(file); 21 } 22 } 23 24 // Handle media upload (image/video) 25 function handleMediaChange(event) { 26 const file = event.target.files[0]; 27 if (file) { 28 const reader = new FileReader(); 29 reader.onloadend = async function () { 30 const mediaBase64 = reader.result; 31 32 let mediaMessage = { message: `<media>${mediaBase64}</media>` }; 33 34 // Include profile picture in media message if available 35 if (profilePicBase64) { 36 mediaMessage.message = `<pfp>${profilePicBase64}</pfp>` + mediaMessage.message; 37 } 38 39 // Send media as a separate message 40 await fetch('/send', { 41 method: 'POST', 42 headers: { 'Content-Type': 'application/json' }, 43 body: JSON.stringify(mediaMessage) 44 }); 45 46 fetchMessages(); 47 }; 48 reader.readAsDataURL(file); 49 } 50 } 51 52 // Fetch messages from the server 53 async function fetchMessages() { 54 const response = await fetch('/messages'); 55 const messages = await response.json(); 56 57 const messageHTML = messages.map(msg => { 58 const base64ImagePattern = /^data:image\/(png|jpeg|jpg|gif);base64,/; 59 const base64VideoPattern = /^data:video\/(mp4|webm|ogg);base64,/; 60 const pfpMatch = msg.match(/<pfp>(.*?)<\/pfp>/); 61 const mediaMatch = msg.match(/<media>(.*?)<\/media>/); 62 let messageText = msg.replace(/<pfp>.*?<\/pfp>/, '').replace(/<media>.*?<\/media>/, ''); 63 let profilePic = ""; 64 let mediaContent = ""; 65 66 // Display profile picture if available 67 if (pfpMatch && base64ImagePattern.test(pfpMatch[1])) { 68 profilePic = `<img src="${pfpMatch[1]}" alt="Profile Picture" style="width: 50px; height: 50px; border-radius: 50%; margin-right: 10px;">`; 69 } 70 71 // Display media as a separate full-size element 72 if (mediaMatch && (base64ImagePattern.test(mediaMatch[1]) || base64VideoPattern.test(mediaMatch[1]))) { 73 if (base64ImagePattern.test(mediaMatch[1])) { 74 mediaContent = `<div>${profilePic}<img src="${mediaMatch[1]}" alt="Media" style="width: 100%; max-width: 600px; margin-top: 10px;"></div>`; 75 } else if (base64VideoPattern.test(mediaMatch[1])) { 76 mediaContent = `<div>${profilePic}<video controls style="width: 100%; max-width: 600px; margin-top: 10px;"><source src="${mediaMatch[1]}" type="video/mp4">Your browser does not support the video tag.</video></div>`; 77 } 78 return mediaContent; // Media is a separate message 79 } 80 81 return `<div style="display: flex; align-items: center; margin-bottom: 10px;">${profilePic}<p>${DOMPurify.sanitize(messageText)}</p></div>`; 82 }).join(''); 83 84 document.getElementById('messages').innerHTML = messageHTML; 85 document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight; 86 } 87 88 // Send text message to the server 89 async function sendMessage() { 90 const message = document.getElementById('messageInput').value; 91 if (message.trim() !== "") { 92 let messageData = { message: DOMPurify.sanitize(message) }; 93 94 // Include profile picture in text message if available 95 if (profilePicBase64) { 96 messageData.message = `<pfp>${profilePicBase64}</pfp>` + messageData.message; 97 } 98 99 await fetch('/send', { 100 method: 'POST', 101 headers: { 'Content-Type': 'application/json' }, 102 body: JSON.stringify(messageData) 103 }); 104 105 document.getElementById('messageInput').value = ''; 106 fetchMessages(); 107 } 108 } 109 110 function toggleSettings() { 111 const modal = document.getElementById('settings'); 112 modal.style.display = modal.style.display === 'flex' ? 'none' : 'flex'; 113 } 114 115 function closeSettings() { 116 document.getElementById('settings').style.display = 'none'; 117 } 118 </script> 119 </head> 120 <body onload="fetchMessages()"> 121 <div class="container"> 122 <div id="messages"></div> 123 <div class="input-container"> 124 <input type="text" id="messageInput" placeholder="Type a message..." autocomplete="off"> 125 <button id="settingsButton" onclick="toggleSettings()">Settings</button> 126 <button onclick="sendMessage()">Send</button> 127 </div> 128 </div> 129 130 <div id="settings"> 131 <div class="settings-content"> 132 <h2>Settings</h2> 133 <!-- Hidden file input for selecting profile picture --> 134 <input type="file" accept="image/*" id="profilePicInput" style="display:none;" onchange="handleProfilePicChange(event)"> 135 <!-- Button that opens the file input for profile picture --> 136 <button onclick="document.getElementById('profilePicInput').click()">Choose Profile Picture</button> 137 138 <!-- Hidden file input for selecting media (image or video) --> 139 <input type="file" accept="image/*,video/*" id="mediaInput" style="display:none;" onchange="handleMediaChange(event)"> 140 <!-- Button that opens the file input for media --> 141 <button onclick="document.getElementById('mediaInput').click()">Send Media</button> 142 143 <button onclick="closeSettings()">Close</button> 144 </div> 145 </div> 146 </body> 147 </html>