adding dev files to master
adding all the dev files, package, webpack etc, including build which will contain minified release
This commit is contained in:
230
src/content/ChatWatcher.js
Normal file
230
src/content/ChatWatcher.js
Normal file
@@ -0,0 +1,230 @@
|
||||
import Emotes from './Emotes';
|
||||
import Message from './Message';
|
||||
import PersistentSyncStorage from 'src/helpers/PersistentSyncStorage';
|
||||
|
||||
|
||||
|
||||
class ChatWatcher {
|
||||
|
||||
|
||||
|
||||
constructor() {
|
||||
this.watchChat = this.watchChat.bind(this);
|
||||
this._chatContainer = null;
|
||||
this._observer = null;
|
||||
this.messages = new Map();
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
this.getChatContainer().then(Emotes.init).then(() => {
|
||||
this.addEmotePopup();
|
||||
this.watchChat();
|
||||
this.parsePreloadedMessages();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
getChatContainer() {
|
||||
// Parent of actual chat (children are messages)
|
||||
const checkForContainer = (res, rej) => {
|
||||
this._chatContainer = document.querySelector('#items.style-scope.yt-live-chat-item-list-renderer');
|
||||
if(this._chatContainer !== null) {
|
||||
res();
|
||||
} else {
|
||||
setTimeout(checkForContainer.bind(this, res, rej), 250);
|
||||
}
|
||||
};
|
||||
return new Promise(checkForContainer);
|
||||
}
|
||||
|
||||
parsePreloadedMessages() {
|
||||
const messages = this._chatContainer.children;
|
||||
|
||||
for(let i = messages.length-1; i >= 0; i--) {
|
||||
const node = messages[i];
|
||||
if(this.isMessageNode(node)) {
|
||||
const message = new Message(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watchChat() {
|
||||
console.log('Chat observer started');
|
||||
this._observer = new MutationObserver(mutations => {
|
||||
|
||||
mutations.forEach(mutation => {
|
||||
|
||||
|
||||
|
||||
const { addedNodes, removedNodes } = mutation;
|
||||
|
||||
// Added nodes
|
||||
if(typeof addedNodes !== 'undefined' && addedNodes.length > 0) {
|
||||
for(let i = 0, length = addedNodes.length-1; i <= length; i++) {
|
||||
const node = addedNodes[i];
|
||||
if(this.isMessageNode(node)) {
|
||||
this.onNewMessage(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Removed nodes
|
||||
if(typeof removedNodes !== 'undefined' && removedNodes.length > 0) {
|
||||
for(let i = 0, length = removedNodes.length-1; i <= length; i++) {
|
||||
const node = removedNodes[i];
|
||||
if(this.isMessageNode(node) && this.isObservedMessage(node)) {
|
||||
this.onObservedMessageRemoved(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this._observer.observe(this._chatContainer, {
|
||||
childList: true,
|
||||
attributes: false,
|
||||
characterData: false,
|
||||
subtree: false
|
||||
});
|
||||
}
|
||||
|
||||
onNewMessage(node) {
|
||||
const message = new Message(node);
|
||||
|
||||
// Don't store message if has 0 emotes
|
||||
if(message.hasEmotes) {
|
||||
this.messages.set(message.id, message);
|
||||
}
|
||||
}
|
||||
|
||||
onObservedMessageRemoved(node) {
|
||||
const messageId = node.getAttribute('message-id');
|
||||
const message = this.messages.get(messageId);
|
||||
if(message != undefined){
|
||||
message.destroy();
|
||||
}
|
||||
|
||||
this.messages.delete(messageId);
|
||||
}
|
||||
|
||||
isMessageNode(node) {
|
||||
return node.tagName === 'YT-LIVE-CHAT-TEXT-MESSAGE-RENDERER';
|
||||
}
|
||||
|
||||
isObservedMessage(node) {
|
||||
return node.getAttribute('message-id') !== null;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
addEmotePopup(){
|
||||
|
||||
// create emote button
|
||||
const emoteButton = document.createElement('button');
|
||||
emoteButton.classList.add('emoteButton');
|
||||
emoteButton.textContent = '';
|
||||
|
||||
// append button to action-buttons list
|
||||
const chatButtonSelectionList = document.getElementById('action-buttons');
|
||||
chatButtonSelectionList.parentNode.insertBefore(emoteButton, chatButtonSelectionList);
|
||||
|
||||
// create popupDiv
|
||||
const popUpDiv = document.createElement('div');
|
||||
popUpDiv.classList.add('popup');
|
||||
popUpDiv.classList.add('hideElement');
|
||||
|
||||
function emoteAppend(keysITer){
|
||||
|
||||
// create divider
|
||||
var hr = document.createElement('hr');
|
||||
hr.classList.add('emoteDivider');
|
||||
|
||||
for (let index = 0; index < keysITer.length; index++) {
|
||||
const element = keysITer[index];
|
||||
var emote_div = document.createElement('emote_div');
|
||||
emote_div.innerHTML = (Emotes.get(element).html);
|
||||
popUpDiv.appendChild(emote_div);
|
||||
}
|
||||
popUpDiv.appendChild(hr);
|
||||
}
|
||||
|
||||
// create text
|
||||
var bttv_text = document.createElement('h2');
|
||||
bttv_text.textContent = "BTTV";
|
||||
bttv_text.classList.add('emotePopUpText');
|
||||
var franker_text = document.createElement('h2');
|
||||
franker_text.textContent = "FrankerFacez";
|
||||
franker_text.classList.add('emotePopUpText');
|
||||
var twitch_text = document.createElement('h2');
|
||||
twitch_text.textContent = "Twitch";
|
||||
twitch_text.classList.add('emotePopUpText');
|
||||
|
||||
|
||||
|
||||
// need ittr to search each dict and append to dom
|
||||
let keysITer = null;
|
||||
|
||||
keysITer = Array.from(Emotes.specialEmotesDictionary.keys());
|
||||
emoteAppend(keysITer);
|
||||
|
||||
if(PersistentSyncStorage.data.options.enableBTTVEmotes){
|
||||
popUpDiv.appendChild(bttv_text);
|
||||
keysITer = Array.from(Emotes.bttv_Dictionary.keys());
|
||||
emoteAppend(keysITer);
|
||||
}
|
||||
|
||||
if(PersistentSyncStorage.data.options.enableFrankerEmotes){
|
||||
popUpDiv.appendChild(franker_text);
|
||||
keysITer = Array.from(Emotes.franker_Dictionary.keys());
|
||||
emoteAppend(keysITer);
|
||||
}
|
||||
|
||||
if(PersistentSyncStorage.data.options.enableTwitchEmotes){
|
||||
popUpDiv.appendChild(twitch_text);
|
||||
keysITer = Array.from(Emotes.twitch_Dictionary.keys());
|
||||
emoteAppend(keysITer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add div to doc
|
||||
chatButtonSelectionList.appendChild(popUpDiv);
|
||||
|
||||
// listen for popup button
|
||||
emoteButton.addEventListener('click', function(){
|
||||
popUpDiv.classList.toggle('hideElement');
|
||||
console.log('emote popup button clicked');
|
||||
});
|
||||
|
||||
// get input area
|
||||
var inputArea = document.querySelector('#input.yt-live-chat-text-input-field-renderer');
|
||||
var inputAreaLabel = document.querySelector('#label.yt-live-chat-text-input-field-renderer');
|
||||
|
||||
// add alt tag to chat
|
||||
function emoteToTextArea(){
|
||||
inputArea.textContent += this.alt + " ";
|
||||
inputArea.focus();
|
||||
inputAreaLabel.textContent = "";
|
||||
popUpDiv.classList.toggle('hideElement');
|
||||
console.log(this.alt + " emote button selected");
|
||||
}
|
||||
|
||||
// listener button for emotes
|
||||
var EMOTICONS = document.getElementsByTagName('img');
|
||||
for (let index = 0; index < EMOTICONS.length; index++) {
|
||||
const element = EMOTICONS[index];
|
||||
element.addEventListener('click', emoteToTextArea, false);
|
||||
}
|
||||
|
||||
console.log((keysITer.length+1) + " Emotes Added");
|
||||
}// end addEmotePopup
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
}// end chat watcher
|
||||
|
||||
export default ChatWatcher;
|
||||
Reference in New Issue
Block a user