Start Session - Both users generate secure key pairs on our server protected with memguard. Each user gets a unique Session ID visible in the placeholder that will be used for pairing
+
Pair Sessions - Exchange Session IDs with your contact (even through insecure mainstream channels). Once exchanged, the Session IDs automatically pair together enabling secure communication
+
Encrypt & Send - After successful pairing, you can encrypt/decrypt messages between the two users. Type your message, encrypt it, then send the encrypted text through any mainstream chat platform
+
End Session - Terminates the secure session by permanently destroying all cryptographic keys, wiping Session IDs, and clearing all encrypted/decrypted content from memory. This makes any future decryption impossible, ensuring your conversation remains truly ephemeral
+ ๐ก๏ธ Virtual Keyboard Protection
+ This virtual keyboard helps protect against keyloggers and malware. Each time you open it, the keys are randomly arranged to prevent pattern recognition by spyware. Use it to safely type sensitive messages without worrying about keyboard monitoring software.
@@ -418,6 +711,21 @@
let currentSessionId = null;
let isNightMode = true;
+ // Check clipboard API support
+ const clipboardSupported = !!(navigator.clipboard && navigator.clipboard.writeText && navigator.clipboard.readText);
+ const isSecureContext = window.isSecureContext || location.protocol === 'https:' || location.hostname === 'localhost';
+
+ console.log('Clipboard API supported:', clipboardSupported);
+ console.log('Secure context:', isSecureContext);
+
+ if (!clipboardSupported) {
+ console.warn('Clipboard API not supported - using fallback methods');
+ }
+
+ if (!isSecureContext) {
+ console.warn('Non-secure context - clipboard access may be limited');
+ }
+
// Use relative URLs for API endpoints
const API_START = "/api/start_session";
const API_END = "/api/end_session";
@@ -425,7 +733,7 @@
const API_BUDDY_ENCRYPT = "/api/buddy_encrypt";
const API_BUDDY_DECRYPT = "/api/buddy_decrypt";
- // DOM Elements
+ // DOM Elements - with null checks
const sessionIdContainer = document.getElementById('sessionIdContainer');
const sessionIdValue = document.getElementById('sessionIdValue');
const copySessionIdBtn = document.getElementById('copySessionIdBtn');
@@ -442,10 +750,18 @@
const statusText = document.getElementById('statusText');
const copyPasteBtn = document.getElementById('copyPasteBtn');
+ // Check if all required elements exist
+ if (!sessionIdContainer || !sessionIdValue || !copySessionIdBtn || !startSessionBtn ||
+ !endSessionBtn || !buddySessionIdInput || !pairSessionsBtn || !textInput ||
+ !buddyEncryptBtn || !buddyDecryptBtn || !statusMessage || !themeToggle ||
+ !statusIndicator || !statusText || !copyPasteBtn) {
+ console.error('Some DOM elements are missing!');
+ showStatus('Interface loading error - please refresh page', true);
+ }
+
let hasClipboardContent = false;
let clipboardContent = '';
-
function showStatus(message, isError = false) {
statusMessage.textContent = message;
statusMessage.className = `status-message ${isError ? 'status-error' : 'status-success'}`;
@@ -526,11 +842,35 @@
}
});
- copySessionIdBtn.addEventListener('click', () => {
- if (!currentSessionId) return;
- navigator.clipboard.writeText(currentSessionId)
- .then(() => showStatus('Session ID copied to clipboard'))
- .catch(error => showStatus('Failed to copy session ID', true));
+ copySessionIdBtn.addEventListener('click', async () => {
+ if (!currentSessionId) {
+ showStatus('No session ID to copy', true);
+ return;
+ }
+
+ try {
+ // Try modern clipboard API first
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ await navigator.clipboard.writeText(currentSessionId);
+ showStatus('Session ID copied to clipboard');
+ } else {
+ // Fallback for older browsers
+ fallbackCopyToClipboard(currentSessionId);
+ showStatus('Session ID copied to clipboard');
+ }
+ } catch (error) {
+ console.error('Copy failed:', error);
+ // Try fallback method
+ try {
+ fallbackCopyToClipboard(currentSessionId);
+ showStatus('Session ID copied to clipboard');
+ } catch (fallbackError) {
+ console.error('Fallback copy failed:', fallbackError);
+ showStatus('Failed to copy session ID - please copy manually', true);
+ // Show session ID for manual copy
+ prompt('Copy this Session ID manually:', currentSessionId);
+ }
+ }
});
pairSessionsBtn.addEventListener('click', async () => {
@@ -734,6 +1074,46 @@
createKeyboard(); // Create new random layout each time
});
+ // Keyboard tooltip functionality
+ const showKeyboardButton = document.getElementById('showKeyboardButton');
+ const keyboardTooltip = document.getElementById('keyboardTooltip');
+
+ showKeyboardButton.addEventListener('mouseenter', () => {
+ keyboardTooltip.style.display = 'block';
+ });
+
+ showKeyboardButton.addEventListener('mouseleave', () => {
+ keyboardTooltip.style.display = 'none';
+ });
+
+ // Readme tooltip functionality
+ const readmeBtn = document.querySelector('a[href="leggimi.html"]');
+ const readmeTooltip = document.getElementById('readmeTooltip');
+
+ if (readmeBtn && readmeTooltip) {
+ readmeBtn.addEventListener('mouseenter', () => {
+ readmeTooltip.style.display = 'block';
+ });
+
+ readmeBtn.addEventListener('mouseleave', () => {
+ readmeTooltip.style.display = 'none';
+ });
+ }
+
+ // Challenge tooltip functionality
+ const challengeBtn = document.querySelector('a[href="challenge.html"]');
+ const challengeTooltip = document.getElementById('challengeTooltip');
+
+ if (challengeBtn && challengeTooltip) {
+ challengeBtn.addEventListener('mouseenter', () => {
+ challengeTooltip.style.display = 'block';
+ });
+
+ challengeBtn.addEventListener('mouseleave', () => {
+ challengeTooltip.style.display = 'none';
+ });
+ }
+
document.getElementById('closeKeyboardButton').addEventListener('click', () => {
document.getElementById('keyboardContainer').style.display = 'none';
});
@@ -797,32 +1177,118 @@
return;
}
try {
- await navigator.clipboard.writeText(text);
+ // Try modern clipboard API first
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ await navigator.clipboard.writeText(text);
+ } else {
+ // Fallback for older browsers
+ fallbackCopyToClipboard(text);
+ }
+
clipboardContent = text;
hasClipboardContent = true;
copyPasteBtn.textContent = 'Paste/Copy';
copyPasteBtn.classList.add('paste-mode');
showStatus('Message copied to clipboard');
} catch (error) {
- showStatus('Failed to copy message', true);
+ console.error('Copy failed:', error);
+ try {
+ fallbackCopyToClipboard(text);
+ clipboardContent = text;
+ hasClipboardContent = true;
+ copyPasteBtn.textContent = 'Paste/Copy';
+ copyPasteBtn.classList.add('paste-mode');
+ showStatus('Message copied to clipboard');
+ } catch (fallbackError) {
+ console.error('Fallback copy failed:', fallbackError);
+ showStatus('Failed to copy message - please copy manually', true);
+ // Show text for manual copy
+ prompt('Copy this message manually:', text);
+ }
}
} else {
// Modalitร Paste
try {
- const text = await navigator.clipboard.readText();
- textInput.value = text;
- showStatus('Message pasted from clipboard');
+ let text = '';
+
+ // Try modern clipboard API first
+ if (navigator.clipboard && navigator.clipboard.readText) {
+ text = await navigator.clipboard.readText();
+ } else {
+ // Fallback - prompt user to paste
+ text = prompt('Please paste your message here:') || '';
+ }
+
+ if (text) {
+ textInput.value = text;
+ showStatus('Message pasted from clipboard');
+ } else {
+ showStatus('No text to paste', true);
+ }
+
hasClipboardContent = false;
copyPasteBtn.textContent = 'Copy/Paste';
copyPasteBtn.classList.remove('paste-mode');
} catch (error) {
- showStatus('Failed to paste message', true);
+ console.error('Paste failed:', error);
+ // Fallback - prompt user
+ const text = prompt('Clipboard access failed. Please paste your message here:') || '';
+ if (text) {
+ textInput.value = text;
+ showStatus('Message pasted manually');
+ } else {
+ showStatus('Failed to paste message', true);
+ }
hasClipboardContent = false;
copyPasteBtn.textContent = 'Copy/Paste';
copyPasteBtn.classList.remove('paste-mode');
}
}
});
+
+ // Fallback copy function for older browsers
+ function fallbackCopyToClipboard(text) {
+ const textArea = document.createElement('textarea');
+ textArea.value = text;
+ textArea.style.position = 'fixed';
+ textArea.style.left = '-999999px';
+ textArea.style.top = '-999999px';
+ document.body.appendChild(textArea);
+ textArea.focus();
+ textArea.select();
+
+ try {
+ const successful = document.execCommand('copy');
+ if (!successful) {
+ throw new Error('Copy command failed');
+ }
+ } finally {
+ document.body.removeChild(textArea);
+ }
+ }
+
+
+
+
+