From b73d5edf6dbc5ec50c6c6bf14ef3176b4ca9d705 Mon Sep 17 00:00:00 2001 From: Mirco Wittrien Date: Wed, 6 Feb 2019 16:21:07 +0100 Subject: [PATCH] added contextmenu to chataliases/chatfilter --- Plugins/ChatAliases/ChatAliases.plugin.js | 6 +- Plugins/ChatFilter/ChatFilter.plugin.js | 244 +++++++++++++++++----- 2 files changed, 196 insertions(+), 54 deletions(-) diff --git a/Plugins/ChatAliases/ChatAliases.plugin.js b/Plugins/ChatAliases/ChatAliases.plugin.js index 5bbe7fe7ff..95234e11d7 100644 --- a/Plugins/ChatAliases/ChatAliases.plugin.js +++ b/Plugins/ChatAliases/ChatAliases.plugin.js @@ -188,9 +188,7 @@ class ChatAliases { // begin of own functions updateContainer (settingspanel, ele) { - var wordvalue = null, replacevalue = null, action = ele.getAttribute("action"); - - var update = () => { + var action = ele.getAttribute("action"), update = () => { BDFDB.saveAllData(this.aliases, this, "words"); var containerhtml = ``; @@ -216,7 +214,7 @@ class ChatAliases { } } else if (action == "remove") { - wordvalue = ele.getAttribute("word"); + var wordvalue = ele.getAttribute("word"); if (wordvalue) { delete this.aliases[wordvalue]; update(); diff --git a/Plugins/ChatFilter/ChatFilter.plugin.js b/Plugins/ChatFilter/ChatFilter.plugin.js index 9d9b9ab936..05f3af52f5 100644 --- a/Plugins/ChatFilter/ChatFilter.plugin.js +++ b/Plugins/ChatFilter/ChatFilter.plugin.js @@ -3,20 +3,22 @@ class ChatFilter { getName () {return "ChatFilter";} - getVersion () {return "3.3.2";} + getVersion () {return "3.3.3";} getAuthor () {return "DevilBro";} getDescription () {return "Allows the user to censor words or block complete messages based on words in the chatwindow.";} initConstructor () { + this.changelog = { + "added":[["ContextMenu","Added an contextmenu entry when right clicking a highlighted/selected word to allow you to faster add new aliases"]] + }; + this.patchModules = { "Message":["componentDidMount","componentDidUpdate"], "StandardSidebarView":"componentWillUnmount" }; - this.configs = ["empty","case","exact"]; - this.css = ` ${BDFDB.dotCNS.messagegroup + BDFDB.dotCN.messageaccessory}.blocked:not(.revealed), ${BDFDB.dotCNS.messagegroup + BDFDB.dotCN.messagemarkup}.blocked:not(.revealed) { @@ -25,15 +27,87 @@ class ChatFilter { }`; this.defaults = { + configs: { + empty: {value:false, description:"Allows the replacevalue to be empty (ignoring the default)"}, + case: {value:false, description:"Handle the wordvalue case sensitive"}, + exact: {value:true, description:"Handle the wordvalue as an exact word and not as part of a word"} + }, replaces: { blocked: {value:"~~BLOCKED~~", title:"Block:", description:"Default Replace Word for blocked Messages:"}, censored: {value:"$!%&%!&", title:"Censor:", description:"Default Replace Word for censored Messages:"} }, settings: { - showMessageOnClick: {value:{blocked:true, censored:true}, enabled:{blocked:true, censored:true}, description:"Show original Message on Click:"}, - hideMessage: {value:{blocked:false, censored:false}, enabled:{blocked:true, censored:false}, description:"Completely hide targeted Messages:"} + addContextMenu: {value:true, inner:false, description:"Add a ContextMenu entry to faster add new blocked/censored Words:"}, + showMessageOnClick: {value:{blocked:true, censored:true}, enabled:{blocked:true, censored:true}, inner:true, description:"Show original Message on Click:"}, + hideMessage: {value:{blocked:false, censored:false}, enabled:{blocked:true, censored:false}, inner:true, description:"Completely hide targeted Messages:"} } }; + + this.chatfilterContextEntryMarkup = + `
+
+
Add to ChatFilter
+
+
+
`; + + this.chatfilterAddModalMarkup = + ` +
+
+
+
+
+
+

Add to ChatFilter

+
+
+ +
+
+
+
+

Block/Censor:

+ +
+
+

With:

+ +
+
+

Translator:

+

Use as Blockword

+
+ +
+

Use as Censorword

+
+ ${Object.keys(this.defaults.configs).map((key, i) => + `
+

${this.defaults.configs[key].description}

+
+
+
`).join('')} +
+
+
+ +
+
+
+
+
`; } getSettingsPanel () { @@ -41,22 +115,24 @@ class ChatFilter { var replaces = BDFDB.getAllData(this, "replaces"); var settings = BDFDB.getAllData(this, "settings"); var settingshtml = `
${this.name}
`; + for (let key in settings) { + if (!this.defaults.settings[key].inner) settingshtml += `

${this.defaults.settings[key].description}

`; + } for (let rtype in replaces) { - var words = BDFDB.loadData(rtype, this, "words"); settingshtml += `

${this.defaults.replaces[rtype].title}

With:

`; for (let key in settings) { - if (this.defaults.settings[key].enabled[rtype]) settingshtml += `

${this.defaults.settings[key].description}

`; + if (this.defaults.settings[key].inner && this.defaults.settings[key].enabled[rtype]) settingshtml += `

${this.defaults.settings[key].description}

`; } settingshtml += `

${this.defaults.replaces[rtype].description}

`; - settingshtml += `

List of ${rtype} Words:

`; - for (let config of this.configs) { + settingshtml += `

List of ${rtype} Words:

`; + for (let config in this.defaults.configs) { settingshtml += `
${config.toUpperCase()}
`; } settingshtml += `
`; - for (let word in words) { - settingshtml += `
${BDFDB.encodeToHTML(word)} (${BDFDB.encodeToHTML(words[word].replace)})
` - for (let config of this.configs) { - settingshtml += `
`; + for (let word in this.words[rtype]) { + settingshtml += `
${BDFDB.encodeToHTML(word)} (${BDFDB.encodeToHTML(this.words[rtype][word].replace)})
` + for (let config in this.defaults.configs) { + settingshtml += `
`; } settingshtml += `
`; } @@ -65,7 +141,7 @@ class ChatFilter { settingshtml += `
`; } var infoHidden = BDFDB.loadData("hideInfo", this, "hideInfo"); - settingshtml += `
Information
`; + settingshtml += `
Information
`; settingshtml += `
Case: Will block/censor words while comparing lowercase/uppercase. apple => apple, not APPLE or AppLe
Not Case: Will block/censor words while ignoring lowercase/uppercase. apple => apple, APPLE and AppLe
Exact: Will block/censor words that are exactly the selected word. apple => apple, not applepie or pineapple
Not Exact: Will block/censor all words containing the selected word. apple => apple, applepie and pineapple
Empty: Ignores the default and set replace word and removes the word/message instead.
`; settingshtml += `
`; @@ -107,6 +183,9 @@ class ChatFilter { if (this.started) return; BDFDB.loadMessage(this); + this.words = BDFDB.loadAllData(this, "words"); + for (let rtype in this.defaults.replaces) if (!BDFDB.isObject(this.words[rtype])) this.words[rtype] = {}; + BDFDB.WebModules.forceAllUpdates(this); } else { @@ -126,16 +205,14 @@ class ChatFilter { // begin of own functions updateContainer (settingspanel, ele) { - var wordvalue = null, replacevalue = null, action = ele.getAttribute("action"), rtype = ele.getAttribute("rtype"), words = BDFDB.loadData(rtype, this, "words") || {}; - - var update = () => { - BDFDB.saveData(rtype, words, this, "words"); + var wordvalue = null, replacevalue = null, action = ele.getAttribute("action"), rtype = ele.getAttribute("rtype"), update = () => { + BDFDB.saveAllData(this.words, this, "words"); var containerhtml = ``; - for (let word in words) { - containerhtml += `
${BDFDB.encodeToHTML(word)} (${BDFDB.encodeToHTML(words[word].replace)})
` - for (let config of this.configs) { - containerhtml += `
`; + for (let word in this.words[rtype]) { + containerhtml += `
${BDFDB.encodeToHTML(word)} (${BDFDB.encodeToHTML(this.words[rtype][word].replace)})
` + for (let config in this.defaults.configs) { + containerhtml += `
`; } containerhtml += `
`; } @@ -148,37 +225,40 @@ class ChatFilter { if (action == "add") { var wordinput = settingspanel.querySelector("#input-" + rtype + "-wordvalue"); var replaceinput = settingspanel.querySelector("#input-" + rtype + "-replacevalue"); - wordvalue = wordinput.value; - replacevalue = replaceinput.value; - if (wordvalue && wordvalue.trim().length > 0) { - wordvalue = wordvalue.trim(); - replacevalue = replacevalue.trim(); - words[wordvalue] = { - replace: replacevalue, - empty: false, - case: false, - exact: true, - regex: false - }; + if (wordinput.value && wordinput.value.trim().length > 0) { wordinput.value = null; replaceinput.value = null; + this.saveWord(wordinput.value.trim(), replaceinput.value.trim()); update(); } } else if (action == "remove") { - wordvalue = ele.getAttribute("word"); + var wordvalue = ele.getAttribute("word"); if (wordvalue) { - delete words[wordvalue]; + delete this.words[rtype][wordvalue]; update(); } } else if (action == "removeall") { BDFDB.openConfirmModal(this, "Are you sure you want to remove all added Words from your list?", () => { - words = {}; + this.words[rtype] = {}; update(); }); } } + + saveWord (wordvalue, replacevalue, rtype, configs = BDFDB.getAllData(this, "configs")) { + if (!wordvalue || !replacevalue) return; + wordvalue = wordvalue.trim(); + replacevalue = replacevalue.trim(); + this.words[rtype][wordvalue] = { + replace: replacevalue, + empty: configs.empty, + case: configs.case, + exact: wordvalue.indexOf(" ") > -1 ? false : configs.exact, + regex: false + }; + } saveReplace (input) { var rtype = input.getAttribute("rtype"); @@ -193,10 +273,9 @@ class ChatFilter { var wordvalue = ele.getAttribute("word"); var config = ele.getAttribute("config"); var rtype = ele.getAttribute("rtype"); - var words = BDFDB.loadData(rtype, this, "words") || {}; - if (wordvalue && words[wordvalue] && config) { - words[wordvalue][config] = ele.checked; - BDFDB.saveData(rtype, words, this, "words"); + if (wordvalue && this.words[rtype][wordvalue] && config) { + this.words[rtype][wordvalue][config] = ele.checked; + BDFDB.saveAllData(this.words, this, "words"); } } @@ -212,6 +291,30 @@ class ChatFilter { BDFDB.saveData("hideInfo", BDFDB.isEleHidden(ele.nextElementSibling), this, "hideInfo"); } + onNativeContextMenu (instance, menu) { + if (instance.props && instance.props.value && instance.props.value.trim() && !menu.querySelector(".chatfilter-item")) { + if ((instance.props.type == "NATIVE_TEXT" || instance.props.type == "CHANNEL_TEXT_AREA") && BDFDB.getData("addContextMenu", this, "settings")) this.appendItem(instance, menu, instance.props.value.trim()); + } + } + + onMessageContextMenu (instance, menu) { + if (instance.props && instance.props.message && instance.props.channel && instance.props.target && !menu.querySelector(".chatfilter-item")) { + let text = document.getSelection().toString().trim(); + if (text && BDFDB.getData("addContextMenu", this, "settings")) this.appendItem(instance, menu, text); + } + } + + appendItem (instance, menu, text) { + let chatfilterContextEntry = BDFDB.htmlToElement(this.chatfilterContextEntryMarkup); + let devgroup = BDFDB.React.findDOMNodeSafe(BDFDB.getOwnerInstance({node:menu,name:"DeveloperModeGroup"})); + if (devgroup) devgroup.parentElement.insertBefore(chatfilterContextEntry, devgroup); + else menu.appendChild(chatfilterContextEntry, menu); + chatfilterContextEntry.querySelector(".chatfilter-item").addEventListener("click", () => { + instance._reactInternalFiber.return.memoizedProps.closeContextMenu(); + this.openAddModal(text); + }); + } + processMessage (instance, wrapper) { wrapper.querySelectorAll(`${BDFDB.dotCNC.messagemarkup + BDFDB.dotCN.messageaccessory}`).forEach(message => {this.hideMessage(message);}); } @@ -246,11 +349,10 @@ class ChatFilter { var settings = BDFDB.getAllData(this, "settings"); var replaces = BDFDB.getAllData(this, "replaces"); - var blockedWords = BDFDB.loadData("blocked", this, "words"); var blocked = false; - for (let bWord in blockedWords) { - var blockedReplace = blockedWords[bWord].empty ? "" : (blockedWords[bWord].replace || replaces.blocked); - var reg = this.createReg(bWord, blockedWords[bWord]); + for (let bWord in this.words.blocked) { + var blockedReplace = this.words.blocked[bWord].empty ? "" : (this.words.blocked[bWord].replace || replaces.blocked); + var reg = this.createReg(bWord, this.words.blocked[bWord]); strings.forEach(string => { if (this.testForEmoji(string, reg)) blocked = true; else if (string.indexOf(' { if (this.testForEmoji(string, reg)) { censored = true; @@ -317,7 +418,6 @@ class ChatFilter { } }); } - if (censored) { newhtml = strings.join(""); message.innerHTML = newhtml; @@ -369,4 +469,48 @@ class ChatFilter { message.addEventListener("click", message.clickChatFilterListener); } } + + openAddModal (wordvalue) { + let chatfilterAddModal = BDFDB.htmlToElement(this.chatfilterAddModalMarkup); + let wordvalueinput = chatfilterAddModal.querySelector("#input-wordvalue"); + let replacevalueinput = chatfilterAddModal.querySelector("#input-replacevalue"); + let addbutton = chatfilterAddModal.querySelector(".btn-add"); + + wordvalueinput.value = wordvalue || ""; + + BDFDB.appendModal(chatfilterAddModal); + + wordvalueinput.addEventListener("input", () => { + if (!wordvalueinput.value.trim()) { + addbutton.disabled = true; + BDFDB.addClass(wordvalueinput, "invalid"); + addbutton.style.setProperty("pointer-events", "none", "important"); + BDFDB.createTooltip("Choose a Wordvalue", {type: "right", color: "red", selector: "chatfilter-disabled-tooltip"}); + } + else { + addbutton.disabled = false; + BDFDB.removeClass(wordvalueinput, "invalid"); + addbutton.style.removeProperty("pointer-events"); + BDFDB.removeEles(".chatfilter-disabled-tooltip"); + } + }); + + BDFDB.addChildEventListener(chatfilterAddModal, "click", BDFDB.dotCNC.backdrop + BDFDB.dotCNC.modalclose + ".btn-add", () => { + BDFDB.removeEles(".chatfilter-disabled-tooltip"); + }); + + addbutton.addEventListener("click", e => { + let configs = {}; + for (let key in this.defaults.configs) { + let configinput = chatfilterAddModal.querySelector("#input-config" + key); + if (configinput) configs[key] = configinput.checked; + } + let rtype = chatfilterAddModal.querySelector("#input-choiceblockcensor").checked ? "censored" : "blocked"; + this.saveWord(wordvalueinput.value.trim(), replacevalueinput.value.trim(), rtype, configs); + BDFDB.saveAllData(this.words, this, "words"); + document.querySelectorAll(`${BDFDB.dotCN.messagemarkup}.blocked, ${BDFDB.dotCN.messageaccessory}.censored, ${BDFDB.dotCN.messagemarkup}.blocked, ${BDFDB.dotCN.messageaccessory}.censored`).forEach(message => {this.resetMessage(message);}); + BDFDB.WebModules.forceAllUpdates(this); + }); + wordvalueinput.focus(); + } }