import Cookies from 'js-cookie';
import HT from '../HT';
/** Abstração de speechSynthesis - Objeto nativo do browser */
class PageSpeechManager {
ht = null;
static defaultLang = 'pt-BR';
static activeMessage = 'Leitor de sites ativado.';
static desactiveMessage = 'Leitor de sites desativado.';
static welcomeMessage = 'Leitor de sites ativado, clique sobre um texto para ouvi-lo.';
static errorMessage = 'Seu navegador não suporta a conversão de texto para voz.';
/** Sintetizador */
synth = null;
firstActivation = null;
_activated = false;
get activated() { return this._activated; }
set activated(value) {
if (value) {
this._activated = value;
// Mensagem de boas vindas
const text = this.firstActivation ? PageSpeechManager.welcomeMessage : PageSpeechManager.activeMessage;
this.speak(text);
// 4 segundos para o texto introdutorio ou 3 para o texto padrão
this.ht.drawer.showSpeechTextDialog(text, this.firstActivation? 4500 : 3000);
// Cookie para primeira ativacao do speech
if (this.firstActivation) {
Cookies.set(FIRST_ACTIVATION_SPEECH_COOKIE_NAME, false, { expires: 7 });
this.firstActivation = false;
}
} else {
this.speak(PageSpeechManager.desactiveMessage);
// Calculamos o tempo em que o modal ficará aberto baseado no tamanho do texto
this.ht.drawer.showSpeechTextDialog(PageSpeechManager.desactiveMessage, 3000);
this._activated = value;
}
this.ht.textManager.activated = !this.ht.textManager.activated;
}
onError = () => {
this.ht.logger.warn(PageSpeechManager.errorMessage);
this.ht.drawer.lockPageSpeechButton();
}
constructor(ht) {
this.ht = ht;
// Verifica se o navegador tem suporte a speechSynthesis com a abordagem implementada
if(typeof window.speechSynthesis == 'undefined' || typeof window.SpeechSynthesisUtterance == 'undefined')
return this.onError();
this.synth = window.speechSynthesis;
// Captura o cookie para exibir ou não a mensagem de boas vindas
this.firstActivation = Cookies.get(FIRST_ACTIVATION_SPEECH_COOKIE_NAME) !== 'false';
// Quando recarregamos a pagina, o sintetizador continua falando, damos o stop() para resolver esse problema.
this.stop();
// Prepara o objeto de requisição
this.prepareUtterance();
// Ouve os cliques
this.ht.textManager.on('validElementClicked', this.onValidElementClicked);
// Ouve o hover
this.ht.textManager.on('validElementOver', this.onValidElementOver);
// Ouve o mouse out
this.ht.textManager.on('validElementOut', this.onValidElementOut);
}
/**
* Prepara a requisição de fala (utterrance)
* @param text - Texto a ser falado
*/
prepareUtterance = (text) => {
let utterance = null;
utterance = new SpeechSynthesisUtterance();
utterance.lang = PageSpeechManager.defaultLang;
utterance.text = text;
return utterance;
}
/**
* Quando um elemento com o texto compativel for clicado
* @param e - Evento
* @param text - Texto tratado (plainText)
*/
onValidElementClicked = (e, text) => {
if (!this.activated) return;
this.ht.logger.info('Texto a ser convertido para audio', text);
this.speak(text);
}
/**
* Quando o mouse/touch foca em um elemento com texto compativel
* @param elem - Elemento que recebeu foco
*/
onValidElementOver = (elem) => {
if (this.activated && !HT.deviceInfo.isMobile) elem.classList.add('ht-speech-hover');
}
/**
* Quando o mouse/touch sai de em um elemento com texto compativel
* @param elem - Elemento que perdeu foco
*/
onValidElementOut = (elem) => {
if (this.activated && elem.classList) elem.classList.remove('ht-speech-hover');
}
/** Fala um texto */
speak = (text) => {
if (!this.activated) return;
let utterance = this.prepareUtterance(text);
this.stop();
this.synth.speak(utterance);
}
/** Para o aúdio atual e limpa a fila de espera */
stop = () => { this.synth.cancel(); }
}
export default PageSpeechManager;