Refactoring and add build-tools

This commit is contained in:
Matvey Tarasov
2020-04-18 17:27:15 +03:00
parent 708cb72028
commit b0b79e46a6
26 changed files with 7896 additions and 172 deletions

View File

@@ -0,0 +1,14 @@
chrome.runtime.onInstalled.addListener(function () {
chrome.storage.sync.set({ isExtensionOn: true }, function () {
console.log('isExtensionOn: ' + true);
});
chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'vk.com' },
})],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
});

126
src/dom/controls.js vendored Normal file
View File

@@ -0,0 +1,126 @@
/**
*
* @param id {String}
* @return {HTMLSpanElement}
*/
import {getChatBody} from "../utils/getChatBody";
function muteBtnHTML(id) {
const element = document.createElement('span');
element.setAttribute('class', 'mute_message');
element.setAttribute('id', `mute${id}`);
element.innerHTML = `
🔇
<span class="mutetooltip">Заглушить</span>
`;
return element;
}
/**
*
* @param chatBody {HTMLElement}
* @return {function(...[*]=)}
*/
export function addControls(chatBody) {
return function (event) {
if (event.target.className === 'im-mess--check fl_l') {
const message = event.target.parentElement;
addControlButton(message, chatBody)
}
}
}
/**
* Create mute button and inset it to the actionArea
* @param actionArea {HTMLElement}
* @param senderId {String}
* @return {HTMLElement}
*/
function addMuteButton(actionArea, senderId) {
const muteButton = muteBtnHTML(senderId);
actionArea.appendChild(muteButton);
muteButton.style.display = "none";
return muteButton;
}
/**
* Add event listeners to the actionArea
* @param actionsArea {HTMLElement}
*/
function addActionAreaEvents(actionsArea) {
actionsArea.parentElement.addEventListener("mouseenter", function (event) {
event.target.getElementsByClassName("mute_message")[0].style.display = "inline-block";
});
actionsArea.parentElement.addEventListener("mouseleave", function (event) {
event.target.getElementsByClassName("mute_message")[0].style.display = "none";
});
}
/**
*
* @param chatBody {HTMLElement}
* @return {function(...[]=)}
*/
function setIdToHideHandle(chatBody) {
return function (event) {
const clickedId = event.target.id.substr(4); // get id of sender from element id
chrome.storage.sync.set({idToHide: clickedId}, function () {
hideExistingMessages(clickedId);
console.log('idToHide: ' + clickedId);
});
}
}
export function hideExistingMessages(id) {
const chatBody = getChatBody();
for (let item of chatBody.children) {
if (item.dataset.peer === id) {
item.style.display = "none";
}
}
}
// Try to add controls until successful. Needed for page refresh.
export function createTryToInitInterval() {
const controlsInterval = setInterval(function () {
if(!tryToInitControls(controlsInterval)){
clearInterval(controlsInterval);
}
}, 200)
return controlsInterval;
}
/**
*
* @param message {HTMLElement}
*/
function addControlButton(message, chatBody) {
const actionsArea = message.getElementsByClassName("im-mess--actions")[0];
if (actionsArea && actionsArea.lastChild.className !== "mute_message") {
const senderId = message.parentElement.parentElement.parentElement["dataset"].peer;
const muteBtn = addMuteButton(actionsArea, senderId);
addActionAreaEvents(actionsArea);
muteBtn.addEventListener("click", setIdToHideHandle(chatBody));
return true;
} else {
return false;
}
}
export function tryToInitControls() {
let status = true;
const chatBody = getChatBody();
if(!chatBody) return false;
for (let item of chatBody.children) {
if (item.className.includes('im-mess-stack _im_mess_stack')) {
let messages = item.children[1].children[1].getElementsByClassName('im-mess im_in _im_mess');
for (let message of messages) {
status = addControlButton(message, chatBody)
}
}
}
return status;
}

49
src/dom/dom.css Normal file
View File

@@ -0,0 +1,49 @@
.mute_message .mutetooltip {
visibility: hidden;
width: 120px;
background-color: #555;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;
/* Position the tooltip text */
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
/* Fade in tooltip */
opacity: 0;
transition: opacity 0.3s;
}
/* Tooltip arrow */
.mute_message .mutetooltip::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
/* Show the tooltip text when you mouse over the tooltip container */
.mute_message:hover .mutetooltip {
visibility: visible;
opacity: 1;
}
.mute_message {
width: 16px;
height: 16px;
position: relative;
display: inline-block;
vertical-align: top;
/*background: url('chrome-extension://__MSG_@@extension_id__/mute.png') !important;*/
background-repeat: no-repeat;
padding: 6px;
}

28
src/dom/hide_element.js Normal file
View File

@@ -0,0 +1,28 @@
import {getChatBody} from "../utils/getChatBody";
export function addNewMessageEventListener() {
const chatBody = getChatBody();
chrome.storage.sync.get('idToHide', function(data) {
let idToHide = data.idToHide;
chatBody.addEventListener('DOMNodeInserted', function(event) {
newMessageHandler(event.target, idToHide)
});
});
}
function newMessageHandler(message, idToHide) {
if (message.className === 'im-mess-stack _im_mess_stack ') {
chrome.storage.sync.get('idToHide', function(data) {
idToHide = data.idToHide;
});
chrome.storage.sync.get('isExtensionOn', function(data) {
if (data.isExtensionOn) {
if (message.dataset.peer === idToHide) {
message.style.display = "none";
}
}
});
}
}

20
src/dom/main.js Normal file
View File

@@ -0,0 +1,20 @@
import './dom.css'
import {createTryToInitInterval, hideExistingMessages, tryToInitControls} from "./controls";
import {UrlController} from "../utils/Url";
import {addNewMessageEventListener} from "./hide_element";
function init() {
const url = new UrlController();
url.onChange((oldUrl, newUrl) => {
// chrome.storage.sync.get('idToHide', function (data) {
// let idToHide = data.idToHide;
// hideExistingMessages(idToHide)
// });
if (tryToInitControls()) {
createTryToInitInterval();
addNewMessageEventListener();
}
})
}
init();

94
src/popup/popup.css Normal file
View File

@@ -0,0 +1,94 @@
body {
min-width: 80px;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.header {
background-color: #2196F3;
color: white;
width: 100vw;
position: relative;
margin-left: -50vw;
left: 50%;
margin-top: -20vw;
margin-bottom: 10vw;
padding-top: 5px;
padding-bottom: 5px;
}
#idToHide {
margin: 10px;
}
.id_list {
background-color: #dcdfde;
color: black;
width: 100vw;
position: relative;
margin-left: -50vw;
left: 50%;
margin-top: 10vw;
padding-top: 5px;
padding-bottom: 5px;
}

21
src/popup/popup.html Normal file
View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="header">
<h3 align="center" id="status"></h3>
</div>
<!--<button id="disableButton">Toggle</button>-->
<div style="text-align: center;">
<label class="switch">
<input type="checkbox" id="disableCheckbox">
<span class="slider round"></span>
</label>
</div>
<div class="id_list">
<div id="idToHide"></div>
</div>
</body>
</html>

47
src/popup/popup.js Normal file
View File

@@ -0,0 +1,47 @@
import './popup.css'
//let disableButton = document.getElementById('disableButton');
let disableCheckbox = document.getElementById('disableCheckbox');
let idToHideDisplay = document.getElementById('idToHide');
let status = document.getElementById('status');
var isExtensionOn;
var idToHide;
var enableText = "Кринж офф";
var disableText = "Кринж он";
chrome.storage.sync.get('isExtensionOn', function(data) {
isExtensionOn = data.isExtensionOn;
disableCheckbox.checked = isExtensionOn;
if (isExtensionOn) {
status.innerHTML = enableText;
} else {
status.innerHTML = disableText;
}
});
chrome.storage.sync.get('idToHide', function(data) {
idToHide = data.idToHide;
idToHideDisplay.innerText = idToHide;
});
disableCheckbox.addEventListener('change', (event) => {
isExtensionOn = event.target.checked;
if (event.target.checked) {
status.innerHTML = enableText;
} else {
status.innerHTML = disableText;
}
chrome.storage.sync.set({isExtensionOn}, function() {
console.log('isExtensionOn: '+isExtensionOn);
});
});
idToHideDisplay.addEventListener('click', function() {
chrome.storage.sync.set({idToHide: ''}, function() {
idToHideDisplay.innerText = '';
console.log('Cleared idToHide');
});
});

47
src/utils/Url.js Normal file
View File

@@ -0,0 +1,47 @@
const INTERVAL_TIME = 100;
export class UrlController {
constructor() {
this._changeListeners = [];
this._interval = null;
this._url = window.location.href;
}
onChange(cb) {
this._changeListeners.push(cb);
if (this._interval === null) {
this._createInterval();
}
}
removeEventListener(cb) {
this._changeListeners = this._changeListeners.filter(item=>item !== cb);
if(this._changeListeners.length === 0) {
this._clearInterval();
}
}
_intervalTick() {
const currentUrl = window.location.href;
if (currentUrl !== this.url) {
this._broadcast(this.url, currentUrl);
this.url = currentUrl;
}
}
_broadcast(oldUrl, newUrl) {
this._changeListeners.forEach(cb => cb(oldUrl, newUrl));
}
_createInterval() {
this.interval = setInterval(() => this._intervalTick(), INTERVAL_TIME)
}
_clearInterval() {
clearInterval(this.interval)
this.interval = null
}
}

3
src/utils/getChatBody.js Normal file
View File

@@ -0,0 +1,3 @@
export function getChatBody() {
return document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0];
}