// Debounce function to prevent multiple triggers on mobile function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Function to update tutorial spans when key display spans are populated function updateTutorialSpans() { const holesailHash = document.getElementById('holesailHash').textContent; const geyserHash = document.getElementById('geyserHash').textContent; const sftpHash = document.getElementById('sftpHash').textContent; document.getElementById('tutorialHolesailHash').textContent = holesailHash; document.getElementById('tutorialGeyserHash').textContent = geyserHash; document.getElementById('tutorialSftpHash').textContent = sftpHash; document.getElementById('tutorialHolesailHashOutput').textContent = holesailHash; document.getElementById('tutorialHolesailHashOutput2').textContent = holesailHash; document.getElementById('tutorialHolesailHashHost').textContent = holesailHash; } // Run initially updateTutorialSpans(); // Observe changes to key display spans const observer = new MutationObserver(updateTutorialSpans); document.querySelectorAll('#holesailHash, #geyserHash, #sftpHash').forEach(span => { observer.observe(span, { childList: true, characterData: true, subtree: true }); }); // Ensure notification is hidden on page load document.addEventListener('DOMContentLoaded', () => { const notification = document.getElementById('copyNotification'); // Add event listeners to copy buttons document.querySelectorAll('.copy-key-btn').forEach(button => { button.addEventListener('click', debounce((event) => { event.preventDefault(); // Prevent default touch behavior if (!event.isTrusted) return; // Ensure user-initiated action const keyElementId = button.getAttribute('data-key-id'); const keyText = document.getElementById(keyElementId).textContent; const keyType = button.getAttribute('data-key-type'); if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(keyText).then(() => { // Use showNotification from app.js window.showNotification(`${keyType} key copied to clipboard!`, 'success', `copy-${keyElementId}`); }).catch(err => { console.error(`Failed to copy ${keyType} key: `, err); window.showNotification(`Failed to copy ${keyType} key.`, 'error', `copy-${keyElementId}`); }); } else { window.showNotification('Clipboard API not supported. Please copy manually.', 'error', `copy-${keyElementId}`); } }, 300)); }); }); // Toggle tutorial section visibility document.getElementById('toggleTutorial').addEventListener('click', () => { const tutorialSection = document.getElementById('tutorialSection'); tutorialSection.classList.toggle('hidden'); }); // Copy summarized tutorial in Markdown with debounced event listener document.getElementById('copyTutorial').addEventListener('click', debounce((event) => { event.preventDefault(); // Prevent default touch behavior if (!event.isTrusted) return; // Ensure user-initiated action const holesailHash = document.getElementById('holesailHash').textContent; const markdownTutorial = `# Join My Minecraft Server with Holesail! Holesail is a secure, peer-to-peer tool that lets you connect to my server without public IPs. 1. **Install Node.js**: Download and install from [nodejs.org](https://nodejs.org/). 2. **Install Holesail**: Open a terminal and run: \`\`\`bash npm i holesail@2.1.0 \`\`\` 3. **Connect to the server**: Use this command with the key: \`\`\`bash holesail ${holesailHash} \`\`\` 4. **Join in Minecraft**: Once Holesail confirms the connection, connect to \`127.0.0.1:25565\` in Minecraft. **Note**: Keep the key private, like an SSH key. No public IPs needed—it's all peer-to-peer!`; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(markdownTutorial).then(() => { window.showNotification('Tutorial copied to clipboard!', 'success', 'copy-tutorial'); }).catch(err => { console.error('Failed to copy tutorial: ', err); window.showNotification('Failed to copy tutorial. Please copy manually.', 'error', 'copy-tutorial'); }); } else { window.showNotification('Clipboard API not supported. Please copy manually.', 'error', 'copy-tutorial'); } }, 300)); // 300ms debounce