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

3
.babelrc Normal file
View File

@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env"]
}

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/node_modules
/.cache
/.idea

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

117
extension/dist/background.js vendored Normal file

File diff suppressed because one or more lines are too long

887
extension/dist/dom.js vendored Normal file

File diff suppressed because one or more lines are too long

21
extension/dist/popup.html vendored 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>
<script src="popup.js"></script></body>
</html>

584
extension/dist/popup.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
{ {
"name": "VK Mute", "name": "VK Mute",
"icons": { "icons": {
"140": "icons/icon140.png", "140": "assets/icons/icon140.png",
"128": "icons/icon128.png", "128": "assets/icons/icon128.png",
"48": "icons/icon48.png" "48": "assets/icons/icon48.png"
}, },
"version": "1.0", "version": "1.0",
"description": "Позволяет заглушить нежелаемых собеседников", "description": "Позволяет заглушить нежелаемых собеседников",
@@ -13,26 +13,17 @@
"storage" "storage"
], ],
"background": { "background": {
"scripts": ["background.js"], "scripts": ["dist/background.js"],
"persistent": false "persistent": false
}, },
"page_action": { "page_action": {
"default_popup": "popup.html" "default_popup": "dist/popup.html"
}, },
"manifest_version": 2, "manifest_version": 2,
"content_scripts": [ "content_scripts": [
{ {
"matches": ["https://*.vk.com/*"], "matches": ["https://*.vk.com/*"],
"js": ["main.js"] "js": ["./dist/dom.js"]
},
{
"matches": ["https://*.vk.com/im*"],
"js": ["hide_element.js"]
},
{
"matches": ["https://*.vk.com/im*"],
"js": ["controls.js"],
"css": ["controls.css"]
} }
] ]
} }

View File

@@ -1,37 +0,0 @@
var idToHide;
var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0];
chatBody.addEventListener('DOMNodeInserted', function(event) {
if (event.target.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 (event.target.dataset.peer === idToHide) {
event.target.style.display = "none";
}
}
});
}
});
chrome.storage.sync.get('idToHide', function(data) {
idToHide = data.idToHide;
});
// Try to hide until successful. Needed for page refresh.
var hideInterval = setInterval(function () {
var chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0];
for (var item of chatBody.children) {
if (item.dataset.peer === idToHide) {
if (item.style.display !== "none") {
item.style.display = "none";
} else {
clearInterval(hideInterval);
}
}
}
}, 200);

View File

@@ -1,9 +0,0 @@
const changeUrlDetect = setInterval((function () {
let oldUrl = '';
return function () {
const currentUrl = window.location.href;
if(currentUrl !== oldUrl){
oldUrl = currentUrl;
}
}
})(),100);

5994
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "vk-mute",
"version": "1.0.0",
"description": "Заглушить собеседника в беседе в ВК. 🔇",
"main": "src/dom/main.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"watch": "webpack --config webpack.config.js --watch"
},
"repository": {
"type": "git",
"url": "git+https://github.com/anatolykopyl/vk-mute.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/anatolykopyl/vk-mute/issues"
},
"homepage": "https://github.com/anatolykopyl/vk-mute#readme",
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"babel-loader": "^8.1.0",
"css-loader": "^3.5.2",
"html-webpack-plugin": "^4.2.0",
"sass": "^1.26.3",
"style-loader": "^1.1.4",
"webpack": "^4.42.1"
},
"dependencies": {
"webpack-cli": "^3.3.11"
}
}

View File

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

View File

@@ -3,6 +3,8 @@
* @param id {String} * @param id {String}
* @return {HTMLSpanElement} * @return {HTMLSpanElement}
*/ */
import {getChatBody} from "../utils/getChatBody";
function muteBtnHTML(id) { function muteBtnHTML(id) {
const element = document.createElement('span'); const element = document.createElement('span');
element.setAttribute('class', 'mute_message'); element.setAttribute('class', 'mute_message');
@@ -19,12 +21,11 @@ function muteBtnHTML(id) {
* @param chatBody {HTMLElement} * @param chatBody {HTMLElement}
* @return {function(...[*]=)} * @return {function(...[*]=)}
*/ */
function addControls(chatBody) { export function addControls(chatBody) {
return function (event) { return function (event) {
console.log(event);
if (event.target.className === 'im-mess--check fl_l') { if (event.target.className === 'im-mess--check fl_l') {
const message = event.target.parentElement; const message = event.target.parentElement;
addControlButton(message) addControlButton(message, chatBody)
} }
} }
} }
@@ -66,21 +67,28 @@ function setIdToHideHandle(chatBody) {
const clickedId = event.target.id.substr(4); // get id of sender from element id const clickedId = event.target.id.substr(4); // get id of sender from element id
chrome.storage.sync.set({idToHide: clickedId}, function () { chrome.storage.sync.set({idToHide: clickedId}, function () {
for (let item of chatBody.children) { hideExistingMessages(clickedId);
if (item.dataset.peer === clickedId) {
item.style.display = "none";
}
}
console.log('idToHide: ' + 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. // Try to add controls until successful. Needed for page refresh.
function createTryToInitInterval() { export function createTryToInitInterval() {
const controlsInterval = setInterval(function () { const controlsInterval = setInterval(function () {
tryToInitControls(controlsInterval) if(!tryToInitControls(controlsInterval)){
clearInterval(controlsInterval);
}
}, 200) }, 200)
return controlsInterval; return controlsInterval;
} }
@@ -88,40 +96,31 @@ function createTryToInitInterval() {
/** /**
* *
* @param message {HTMLElement} * @param message {HTMLElement}
* @param intervalForClean {Number?}
*/ */
function addControlButton(message, intervalForClean) { function addControlButton(message, chatBody) {
const actionsArea = message.getElementsByClassName("im-mess--actions")[0]; const actionsArea = message.getElementsByClassName("im-mess--actions")[0];
if (actionsArea && actionsArea.lastChild.className !== "mute_message") { if (actionsArea && actionsArea.lastChild.className !== "mute_message") {
const senderId = message.parentElement.parentElement.parentElement["dataset"].peer; const senderId = message.parentElement.parentElement.parentElement["dataset"].peer;
const muteBtn = addMuteButton(actionsArea, senderId); const muteBtn = addMuteButton(actionsArea, senderId);
addActionAreaEvents(actionsArea); addActionAreaEvents(actionsArea);
muteBtn.addEventListener("click", setIdToHideHandle(chatBody)); muteBtn.addEventListener("click", setIdToHideHandle(chatBody));
} else if (intervalForClean) { return true;
clearInterval(intervalForClean) } else {
return false;
} }
} }
/** export function tryToInitControls() {
* Function hide and mark messages let status = true;
* @param intervalForClear {Number} const chatBody = getChatBody();
*/ if(!chatBody) return false;
function tryToInitControls(intervalForClear) {
const chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0];
for (let item of chatBody.children) { for (let item of chatBody.children) {
if (item.className.includes('im-mess-stack _im_mess_stack')) { if (item.className.includes('im-mess-stack _im_mess_stack')) {
let messages = item.children[1].children[1].getElementsByClassName('im-mess im_in _im_mess'); let messages = item.children[1].children[1].getElementsByClassName('im-mess im_in _im_mess');
for (let message of messages) { for (let message of messages) {
addControlButton(message, intervalForClear) status = addControlButton(message, chatBody)
} }
} }
} }
return status;
} }
(function init() {
const chatBody = document.getElementsByClassName("_im_peer_history im-page-chat-contain")[0];
chatBody.addEventListener('DOMNodeInserted', addControls);
createTryToInitInterval();
})();

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

View File

@@ -1,23 +1,21 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="popup.css"> </head>
</head> <body>
<body> <div class="header">
<div class="header"> <h3 align="center" id="status"></h3>
<h3 align="center" id="status"></h3> </div>
</div> <!--<button id="disableButton">Toggle</button>-->
<!--<button id="disableButton">Toggle</button>--> <div style="text-align: center;">
<div style="text-align: center;"> <label class="switch">
<label class="switch"> <input type="checkbox" id="disableCheckbox">
<input type="checkbox" id="disableCheckbox"> <span class="slider round"></span>
<span class="slider round"></span> </label>
</label> </div>
</div> <div class="id_list">
<div class="id_list"> <div id="idToHide"></div>
<div id="idToHide"></div> </div>
</div> </body>
<script src="popup.js"></script>
</body>
</html> </html>

View File

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

40
webpack.config.js Normal file
View File

@@ -0,0 +1,40 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
devtool: "inline-source-map",
entry: {
dom: './src/dom/main.js',
background: './src/background/background.js',
popup: './src/popup/popup.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'extension/dist')
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
}
]
},
plugins: [new HtmlWebpackPlugin({
template: "./src/popup/popup.html",
filename: "popup.html",
chunks: ['popup']
})]
}