// Global functionality for wash.dev // Initialize the app document.addEventListener('DOMContentLoaded', function() { initLiveFeed(); initSmoothScrolling(); initPricingButtons(); }); // Live feed simulation function initLiveFeed() { const feed = document.getElementById('live-feed'); if (!feed) return; const jobs = [ { file: 'contract.pdf', threat: 'removed 12 zero-width chars, embedded JS', time: '2s ago' }, { file: 'resume.docx', threat: 'stripped VBA macro, removed metadata', time: '5s ago' }, { file: 'presentation.pptx', threat: 'cleaned embedded objects, removed scripts', time: '8s ago' }, { file: 'image.jpg', threat: 'LSB stego in red channel detected', time: '12s ago' }, { file: 'document.txt', threat: 'removed zero-width injections', time: '15s ago' }, { file: 'invoice.pdf', threat: 'cleaned form fields, removed JavaScript', time: '18s ago' }, { file: 'report.docx', threat: 'stripped macros, cleaned metadata', time: '22s ago' }, { file: 'spreadsheet.xlsx', threat: 'removed embedded scripts', time: '25s ago' } ]; let currentIndex = 0; function addNewJob() { const job = jobs[currentIndex % jobs.length]; currentIndex++; const jobElement = document.createElement('div'); jobElement.className = 'flex items-center justify-between py-3 px-4 bg-green-50 rounded border border-green-200 animate-fade-in-up'; jobElement.innerHTML = `
Processed ${job.file} – ${job.threat}
${job.time} `; // Add to top of feed feed.insertBefore(jobElement, feed.firstChild); // Remove jobs older than 10 const jobsElements = feed.children; if (jobsElements.length > 10) { feed.removeChild(jobsElements[jobsElements.length - 1]); } // Update timestamps updateTimestamps(); } function updateTimestamps() { const jobsElements = feed.children; let timeCounter = 2; for (let i = 0; i < jobsElements.length; i++) { const timeElement = jobsElements[i].querySelector('.text-gray-500'); if (timeElement && !timeElement.textContent.includes('ago')) { timeElement.textContent = `${timeCounter}s ago`; timeCounter += 3; } } } // Add new job every 2 seconds setInterval(addNewJob, 2000); } // Smooth scrolling for navigation function initSmoothScrolling() { document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } // Pricing button interactions function initPricingButtons() { document.querySelectorAll('button').forEach(button => { button.addEventListener('click', function(e) { if (this.textContent.includes('Start with') || this.textContent.includes('Buy Credits')) { e.preventDefault(); // In a real app, this would redirect to checkout showNotification('Redirecting to secure checkout...', 'success'); setTimeout(() => { window.location.href = 'app.wash.dev'; }, 1500); } }); }); } // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `fixed top-4 right-4 z-50 px-6 py-4 rounded-lg shadow-lg notification ${ type === 'success' ? 'bg-green-500 text-white' : type === 'error' ? 'bg-red-500 text-white' : 'bg-blue-500 text-white' }`; notification.textContent = message; document.body.appendChild(notification); // Auto remove after 3 seconds setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 3000); } // Utility functions function formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } function formatTime(seconds) { if (seconds < 60) { return `${seconds.toFixed(1)}s`; } else { const minutes = Math.floor(seconds / 60); const remainingSeconds = (seconds % 60).toFixed(1); return `${minutes}m ${remainingSeconds}s`; } } // API simulation const mockAPI = { async cleanDocument(file) { // Simulate API call await new Promise(resolve => setTimeout(resolve, Math.random() * 3000 + 1000)); const threats = [ 'zero-width characters', 'embedded JavaScript', 'LSB steganography', 'VBA macros', 'metadata injections', 'hidden text', 'form field scripts' ]; const foundThreats = []; const threatCount = Math.floor(Math.random() * 3) + 1; for (let i = 0; i < threatCount; i++) { foundThreats.push(threats[Math.floor(Math.random() * threats.length)]); } return { success: true, threats: foundThreats, processingTime: Math.random() * 4 + 1, cleanText: 'Clean document text...', cleanPDF: 'blob:clean-pdf-data', metadata: { originalSize: file.size, cleanedSize: Math.floor(file.size * 0.85), threatsRemoved: foundThreats.length } }; } }; // Export for use in other scripts window.Wash = { showNotification, formatBytes, formatTime, mockAPI };