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);
}