async function init() { new MutationObserver(function (mutationsList) { for (const mutation of mutationsList) { if (mutation.target.closest("form")) { chatBtns(); } } }).observe(document.body, { childList: true, subtree: true, }); } function chatBtns() { const synth = window.speechSynthesis; let currentUtterance = null; let currentIndex = -1; const list = Array.from(document.querySelectorAll("main >div>div>div>div>div")); list.forEach((i, idx) => { if (i.querySelector('.chat-item-copy')) return; if (!i.querySelector('button.rounded-md')) return; if (!i.querySelector('.self-end')) return; const cpbtn = i.querySelector('button.rounded-md').cloneNode(true); cpbtn.classList.add('chat-item-copy'); cpbtn.title = 'Copy to clipboard'; cpbtn.innerHTML = setIcon('copy'); i.querySelector('.self-end').appendChild(cpbtn); cpbtn.onclick = () => { copyToClipboard(i?.innerText?.trim() || '', cpbtn); } const saybtn = i.querySelector('button.rounded-md').cloneNode(true); saybtn.classList.add('chat-item-voice'); saybtn.title = 'Say'; saybtn.innerHTML = setIcon('voice'); i.querySelector('.self-end').appendChild(saybtn); saybtn.onclick = () => { if (currentUtterance && currentIndex !== -1) { synth.cancel(); if (idx === currentIndex) { saybtn.innerHTML = setIcon('voice'); currentUtterance = null; currentIndex = -1; return; } else if (list[currentIndex].querySelector('.chat-item-voice')) { list[currentIndex].querySelector('.chat-item-voice').innerHTML = setIcon('voice'); list[idx].querySelector('.chat-item-voice').innerHTML = setIcon('speaking'); } } const txt = i?.innerText?.trim() || ''; const lang = 'en-US'; if (!txt) return; const utterance = new SpeechSynthesisUtterance(txt); utterance.voice = speechSynthesis.getVoices().find(voice => voice.lang === lang); currentIndex = idx; utterance.lang = lang; utterance.rate = 0.7; utterance.pitch = 1.1; utterance.volume = 1; synth.speak(utterance); amISpeaking = synth.speaking; saybtn.innerHTML = setIcon('speaking'); currentUtterance = utterance; currentIndex = idx; utterance.onend = () => { saybtn.innerHTML = setIcon('voice'); currentUtterance = null; currentIndex = -1; } } }) } function copyToClipboard(text, btn) { window.clearTimeout(window.__cpTimeout); btn.innerHTML = setIcon('cpok'); if (navigator.clipboard) { navigator.clipboard.writeText(text); } else { var textarea = document.createElement('textarea'); document.body.appendChild(textarea); textarea.style.position = 'fixed'; textarea.style.clip = 'rect(0 0 0 0)'; textarea.style.top = '10px'; textarea.value = text; textarea.select(); document.execCommand('copy', true); document.body.removeChild(textarea); } window.__cpTimeout = setTimeout(() => { btn.innerHTML = setIcon('copy'); }, 1000); } function setIcon(type) { return { copy: ``, cpok: ``, voice: ``, speaking: ``, }[type]; } if ( document.readyState === "complete" || document.readyState === "interactive" ) { init(); } else { document.addEventListener("DOMContentLoaded", init); }