From 7e4d0fb40eed5ffbd91909b7cef7a17987f99da4 Mon Sep 17 00:00:00 2001 From: Mirco Wittrien Date: Fri, 20 Dec 2019 14:01:16 +0100 Subject: [PATCH] Update ChatAliases.plugin.js --- Plugins/ChatAliases/ChatAliases.plugin.js | 635 +++++++++++----------- 1 file changed, 324 insertions(+), 311 deletions(-) diff --git a/Plugins/ChatAliases/ChatAliases.plugin.js b/Plugins/ChatAliases/ChatAliases.plugin.js index 9c533df948..f0e9edb31c 100644 --- a/Plugins/ChatAliases/ChatAliases.plugin.js +++ b/Plugins/ChatAliases/ChatAliases.plugin.js @@ -3,7 +3,7 @@ class ChatAliases { getName () {return "ChatAliases";} - getVersion () {return "2.0.2";} + getVersion () {return "2.0.3";} getAuthor () {return "DevilBro";} @@ -11,17 +11,27 @@ class ChatAliases { constructor () { this.changelog = { - "fixed":[["Little Fix","Sendings works again, but some stuff is still broken"]] + "fixed":[["New WYSIWYG Textarea","Fixed for the new WYSIWYG Textarea that is hidden by experiments"]], + "improved":[["New Library Structure & React","Restructured my Library and switched to React rendering instead of DOM manipulation"]] }; this.patchedModules = { + before: { + ChannelTextArea: "render" + }, after: { - ChannelTextArea: ["render", "componentDidMount"] + ChannelTextArea: "render" } }; } initConstructor () { + this.css = ` + ${BDFDB.dotCN.autocompleteicon} { + flex: 0 0 auto; + } + `; + this.defaults = { configs: { case: {value:false, description:"Handle the wordvalue case sensitive"}, @@ -38,103 +48,144 @@ class ChatAliases { minAliasLength: {value:2, min:1, description:"Minimal Character Length to open Autocomplete-Menu:"} } }; - - this.chataliasesAddModalMarkup = - ` -
-
-
-
-
-
-

Add to ChatAliases

-
-
- -
-
-
-
-

Replace:

- -
-
-

With:

- - -
- ${BDFDB.ArrayUtils.remove(Object.keys(this.defaults.configs), "file").map((key, i) => - `
-

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

-
-
-
`).join('')} -
-
-
- -
-
-
-
-
`; } - getSettingsPanel () { + getSettingsPanel (collapseStates = {}) { if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return; let settings = BDFDB.DataUtils.get(this, "settings"); - var amounts = BDFDB.DataUtils.get(this, "amounts"); - var settingshtml = `
${this.name}
`; - for (let key in settings) { - settingshtml += `

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

`; - } - for (let key in amounts) { - settingshtml += `

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

`; - } - settingshtml += `

Replace:

With:

`; - settingshtml += `

List of Chataliases:

`; - for (let config in this.defaults.configs) { - settingshtml += `
${config.toUpperCase()}
`; - } - settingshtml += `
`; - for (let word in this.aliases) { - settingshtml += `
`; - for (let config in this.defaults.configs) { - settingshtml += `
`; - } - settingshtml += `
`; - } - settingshtml += `
`; - settingshtml += `

Remove all added words.

`; - var infoHidden = BDFDB.DataUtils.load(this, "hideInfo", "hideInfo"); - settingshtml += `
Information
`; - settingshtml += `
Case: Will replace words while comparing lowercase/uppercase. apple => apple, not APPLE or AppLe
Not Case: Will replace words while ignoring lowercase/uppercase. apple => apple, APPLE and AppLe
Exact: Will replace words that are exactly the replaceword. apple to pear => applepie stays applepie
Not Exact: Will replace words anywhere they appear. apple to pear => applepieapple to pearpiepear
Autoc: Will appear in the Autocomplete Menu (if enabled).
Regex: Will treat the entered wordvalue as a regular expression. Help
File: If the replacevalue is a filepath it will try to upload the file located at the filepath.
`; - settingshtml += `
`; - - let settingspanel = BDFDB.DOMUtils.create(settingshtml); - - BDFDB.initElements(settingspanel, this); - - BDFDB.ListenerUtils.add(this, settingspanel, "keypress", ".wordInputs", e => {if (e.which == 13) this.updateContainer(settingspanel, e.currentTarget);}); - BDFDB.ListenerUtils.add(this, settingspanel, "keyup", BDFDB.dotCN.gamenameinput, e => {this.updateWord(e.currentTarget);}); - BDFDB.ListenerUtils.add(this, settingspanel, "click", ".btn-addword, .remove-word, .remove-all", e => {this.updateContainer(settingspanel, e.currentTarget);}); - BDFDB.ListenerUtils.add(this, settingspanel, "click", BDFDB.dotCN.checkboxinput, e => {this.updateConfig(e.currentTarget);}); - BDFDB.ListenerUtils.add(this, settingspanel, "click", ".toggle-info", e => {this.toggleInfo(e.currentTarget);}); - return settingspanel; + let amounts = BDFDB.DataUtils.get(this, "amounts"); + let settingspanel, settingsitems = [], inneritems = []; + + for (let key in settings) inneritems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + className: BDFDB.disCN.marginbottom8, + type: "Switch", + plugin: this, + keys: ["settings", key], + label: this.defaults.settings[key].description, + value: settings[key] + })); + for (let key in amounts) inneritems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + className: BDFDB.disCN.marginbottom8, + type: "TextInput", + childProps: { + type: "number" + }, + plugin: this, + keys: ["amounts", key], + label: this.defaults.amounts[key].description, + basis: "20%", + min: this.defaults.amounts[key].min, + max: this.defaults.amounts[key].max, + value: amounts[key] + })); + settingsitems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Settings", + collapseStates: collapseStates, + children: inneritems + })); + let values = {wordvalue:"", replacevalue:""}; + settingsitems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Add new Alias", + collapseStates: collapseStates, + dividertop: true, + children: [ + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { + type: "Button", + label: "Pick a Wordvalue and Replacevalue:", + key: "ADDBUTTON", + disabled: !Object.keys(values).every(valuename => values[valuename]), + children: BDFDB.LanguageUtils.LanguageStrings.ADD, + onClick: _ => { + this.saveWord(values.wordvalue, values.replacevalue, settingspanel.querySelector(".input-replacevalue input[type='file']")); + this.refreshSettings(settingspanel, collapseStates); + } + }), + this.createInputs(values) + ].flat(10).filter(n => n) + })); + if (!BDFDB.ObjectUtils.isEmpty(this.aliases)) settingsitems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Added Aliases", + collapseStates: collapseStates, + dividertop: true, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsList, { + settings: Object.keys(this.defaults.configs), + data: Object.keys(this.aliases).map((wordvalue, i) => Object.assign({}, this.aliases[wordvalue], { + key: wordvalue, + label: wordvalue + })), + renderLabel: data => BDFDB.ReactUtils.createElement("div", { + style: {width: "100%"}, + children: [ + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, { + value: data.label, + placeholder: data.label, + size: BDFDB.LibraryComponents.TextInput.Sizes.MINI, + maxLength: 100000000000000000000, + onChange: value => { + this.aliases[value] = this.aliases[data.label]; + delete this.aliases[data.label]; + data.label = value; + BDFDB.DataUtils.save(this.aliases, this, "words"); + } + }), + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, { + value: data.replace, + placeholder: data.replace, + size: BDFDB.LibraryComponents.TextInput.Sizes.MINI, + maxLength: 100000000000000000000, + onChange: value => { + this.aliases[data.label].replace = value; + BDFDB.DataUtils.save(this.aliases, this, "words"); + } + }) + ] + }), + onCheckboxChange: (value, instance) => { + this.aliases[instance.props.cardId][instance.props.settingId] = value; + BDFDB.DataUtils.save(this.aliases, this, "words"); + }, + onRemove: (e, instance) => { + delete this.aliases[instance.props.cardId]; + BDFDB.DataUtils.save(this.aliases, this, "words"); + this.refreshSettings(settingspanel, collapseStates); + } + }) + })); + settingsitems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Remove All", + collapseStates: collapseStates, + dividertop: true, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { + type: "Button", + className: BDFDB.disCN.marginbottom8, + color: BDFDB.LibraryComponents.Button.Colors.RED, + label: "Remove all added Aliases", + onClick: _ => { + BDFDB.ModalUtils.confirm(this, "Are you sure you want to remove all added Aliases?", _ => { + this.aliases = {}; + BDFDB.DataUtils.remove(this, "words"); + this.refreshSettings(settingspanel, collapseStates); + }); + }, + children: BDFDB.LanguageUtils.LanguageStrings.REMOVE + }) + })); + settingsitems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Config Guide", + collapseStates: collapseStates, + dividertop: true, + children: ["Case: Will replace words while comparing lowercase/uppercase. apple => apple, not APPLE or AppLe", "Not Case: Will replace words while ignoring lowercase/uppercase. apple => apple, APPLE and AppLe", "Exact: Will replace words that are exactly the replaceword. apple to pear => applepie stays applepie", "Not Exact: Will replace words anywhere they appear. apple to pear => applepieapple to pearpiepear", "Autoc: Will appear in the Autocomplete Menu (if enabled).", "Regex: Will treat the entered wordvalue as a regular expression. Help", "File: If the replacevalue is a filepath it will try to upload the file located at the filepath."].map(string => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormText, { + type: BDFDB.LibraryComponents.FormComponents.FormTextTypes.DESCRIPTION, + children: string + })) + })); + + return settingspanel = BDFDB.PluginUtils.createSettingsPanel(this, settingsitems); + } + + refreshSettings (settingspanel, collapseStates) { + settingspanel.parentElement.appendChild(this.getSettingsPanel(collapseStates)); + settingspanel.remove(); } //legacy @@ -168,10 +219,6 @@ class ChatAliases { this.aliases = BDFDB.DataUtils.load(this, "words"); - BDFDB.ListenerUtils.add(document, "click", e => { - if (!e.target.tagName === "TEXTAREA") BDFDB.DOMUtils.remove(".autocompleteAliases", ".autocompleteAliasesRow"); - }); - BDFDB.ModuleUtils.forceAllUpdates(this); } else console.error(`%c[${this.getName()}]%c`, "color: #3a71c1; font-weight: 700;", "", "Fatal Error: Could not load BD functions!"); @@ -189,109 +236,6 @@ class ChatAliases { // begin of own functions - updateContainer (settingspanel, ele) { - var wordvalue = null, replacevalue = null, action = ele.getAttribute("action"); - - var update = () => { - BDFDB.DataUtils.save(this.aliases, this, "words"); - - var containerhtml = ``; - for (let word in this.aliases) { - containerhtml += `
`; - for (let config in this.defaults.configs) { - containerhtml += `
`; - } - containerhtml += `
`; - } - settingspanel.querySelector(".alias-list").innerHTML = containerhtml; - BDFDB.initElements(settingspanel, this); - }; - - if (action == "add") { - var wordinput = settingspanel.querySelector("#input-wordvalue"); - var replaceinput = settingspanel.querySelector("#input-replacevalue"); - if (wordinput.value && wordinput.value.trim().length > 0 && replaceinput.value && replaceinput.value.trim().length > 0) { - this.saveWord(wordinput.value.trim(), replaceinput.value.trim(), settingspanel.querySelector("#input-file")); - wordinput.value = null; - replaceinput.value = null; - update(); - } - } - else if (action == "remove") { - wordvalue = ele.getAttribute("word"); - if (wordvalue) { - delete this.aliases[wordvalue]; - update(); - } - } - else if (action == "removeall") { - BDFDB.ModalUtils.confirm(this, "Are you sure you want to remove all added Words from your list?", () => { - this.aliases = {}; - update(); - }); - } - } - - saveWord (wordvalue, replacevalue, fileselection, configs = BDFDB.DataUtils.get(this, "configs")) { - if (!wordvalue || !replacevalue || !fileselection) return; - var filedata = null; - if (fileselection.files && fileselection.files[0] && BDFDB.LibraryRequires.fs.existsSync(replacevalue)) { - filedata = JSON.stringify({ - data: BDFDB.LibraryRequires.fs.readFileSync(replacevalue).toString("base64"), - name: fileselection.files[0].name, - type: fileselection.files[0].type - }); - } - this.aliases[wordvalue] = { - replace: replacevalue, - filedata: filedata, - case: configs.case, - exact: wordvalue.indexOf(" ") > -1 ? false : configs.exact, - autoc: configs.regex ? false : configs.autoc, - regex: configs.regex, - file: filedata != null - }; - } - - updateWord (ele) { - BDFDB.TimeUtils.clear(ele.updateTimeout); - ele.updateTimeout = BDFDB.TimeUtils.timeout(() => { - var card = ele.parentElement.parentElement; - var oldwordvalue = ele.getAttribute("word"); - if (oldwordvalue && this.aliases[oldwordvalue]) { - var wordinput = card.querySelector(".word-name"); - var replaceinput = card.querySelector(".replace-name"); - var removebutton = card.querySelector(".remove-word"); - var newwordvalue = wordinput.value; - var newreplacevalue = replaceinput.value; - wordinput.setAttribute("word", newwordvalue); - wordinput.setAttribute("value", newwordvalue); - replaceinput.setAttribute("word", newwordvalue); - replaceinput.setAttribute("value", newreplacevalue); - removebutton.setAttribute("word", newwordvalue); - this.aliases[newwordvalue] = this.aliases[oldwordvalue]; - this.aliases[newwordvalue].replace = newreplacevalue; - if (newwordvalue != oldwordvalue) delete this.aliases[oldwordvalue]; - BDFDB.DataUtils.save(this.aliases, this, "words"); - } - },500); - } - - updateConfig (ele) { - var wordvalue = ele.getAttribute("word"); - var config = ele.getAttribute("config"); - if (wordvalue && this.aliases[wordvalue] && config) { - this.aliases[wordvalue][config] = ele.checked; - BDFDB.DataUtils.save(this.aliases, this, "words"); - } - } - - toggleInfo (ele) { - BDFDB.DOMUtils.toggleClass(ele.querySelector("svg"), BDFDB.disCN.directionright); - BDFDB.DOMUtils.toggle(ele.nextElementSibling); - BDFDB.DataUtils.save(BDFDB.DOMUtils.isHidden(ele.nextElementSibling), this, "hideInfo", "hideInfo"); - } - onSettingsClosed () { if (this.SettingsUpdated) { delete this.SettingsUpdated; @@ -301,35 +245,119 @@ class ChatAliases { onNativeContextMenu (e) { if (e.instance.props.value && e.instance.props.value.trim()) { - if ((e.instance.props.type == "NATIVE_TEXT" || e.instance.props.type == "CHANNEL_TEXT_AREA") && BDFDB.DataUtils.get(this, "settings", "addContextMenu")) this.appendItem(e, e.instance.props.value.trim()); + if ((e.instance.props.type == "NATIVE_TEXT" || e.instance.props.type == "CHANNEL_TEXT_AREA") && BDFDB.DataUtils.get(this, "settings", "addContextMenu")) this.injectItem(e, e.instance.props.value.trim()); } } onMessageContextMenu (e) { if (e.instance.props.message && e.instance.props.channel && e.instance.props.target) { let text = document.getSelection().toString().trim(); - if (text && BDFDB.DataUtils.get(this, "settings", "addContextMenu")) this.appendItem(e, text); + if (text && BDFDB.DataUtils.get(this, "settings", "addContextMenu")) this.injectItem(e, text); } } - appendItem (e, text) { + injectItem (e, text) { let [children, index] = BDFDB.ReactUtils.findChildren(e.returnvalue, {name:["FluxContainer(MessageDeveloperModeGroup)", "DeveloperModeGroup"]}); children.splice(index > -1 ? index : children.length, 0, BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ContextMenuItems.Group, { - children: [ - BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ContextMenuItems.Item, { - label: "Add to ChatAliases", - action: _ => { - BDFDB.ContextMenuUtils.close(e.instance); - this.openAddModal(text); - } - }) - ] + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.ContextMenuItems.Item, { + label: "Add to ChatAliases", + action: _ => { + BDFDB.ContextMenuUtils.close(e.instance); + this.openAddModal(text); + } + }) })); } processChannelTextArea (e) { if (e.instance.props.channel && e.instance.props.type) { - if (e.returnvalue) { + if (!e.returnvalue) { + e.instance.props.autocompleteOptions.ALIASES = { + matches: (firstChar, rest, isFirstWord) => { + let currentLastWord = e.instance._editorRef.getCurrentWord().word; + for (let word in this.aliases) { + let aliasdata = this.aliases[word]; + if (!aliasdata.regex && aliasdata.autoc) { + if (aliasdata.exact) { + if (aliasdata.case && word.indexOf(currentLastWord) == 0) return true; + else if (!aliasdata.case && word.toLowerCase().indexOf(currentLastWord.toLowerCase()) == 0) return true; + } + else { + if (aliasdata.case && word.indexOf(currentLastWord) > -1) return true; + else if (!aliasdata.case && word.toLowerCase().indexOf(currentLastWord.toLowerCase()) > -1) return true; + } + } + } + return false; + }, + queryResults: (rest) => { + let currentLastWord = e.instance._editorRef.getCurrentWord().word; + let matches = []; + for (let word in this.aliases) { + let aliasdata = Object.assign({word}, this.aliases[word]); + if (!aliasdata.regex && aliasdata.autoc) { + if (aliasdata.exact) { + if (aliasdata.case && word.indexOf(currentLastWord) == 0) matches.push(aliasdata); + else if (!aliasdata.case && word.toLowerCase().indexOf(currentLastWord.toLowerCase()) == 0) matches.push(aliasdata); + } + else { + if (aliasdata.case && word.indexOf(currentLastWord) > -1) matches.push(aliasdata); + else if (!aliasdata.case && word.toLowerCase().indexOf(currentLastWord.toLowerCase()) > -1) matches.push(aliasdata); + } + } + } + if (matches.length) return {aliases: matches}; + }, + renderResults: (rest, currentSelected, setSelected, chooseSelected, autocompletes) => { + return [ + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.AutocompleteComponents.Title, { + title: [ + "Aliases: ", + BDFDB.ReactUtils.createElement("strong", { + children: e.instance._editorRef.getCurrentWord().word + }) + ] + }), + autocompletes.aliases.map((aliasdata, i) => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.AutocompleteComponents.Generic, { + onClick: chooseSelected, + onHover: setSelected, + index: i, + selected: currentSelected === i, + text: aliasdata.word, + description: aliasdata.replace, + })) + ].flat(10).filter(n => n); + }, + getPlainText: (eventOrIndex, autocompletes) => { + return eventOrIndex._targetInst ? eventOrIndex._targetInst.memoizedProps.text : (typeof eventOrIndex == "number" ? autocompletes.aliases[eventOrIndex].word : ""); + }, + getRawText: (eventOrIndex, autocompletes) => { + return eventOrIndex._targetInst ? eventOrIndex._targetInst.memoizedProps.description : (typeof eventOrIndex == "number" ? autocompletes.aliases[eventOrIndex].replace : ""); + } + }; + if (e.instance.state.autocompleteType == "COMMAND" && BDFDB.ArrayUtils.is(e.instance.props.autocompletes.commands)) { + for (let i in e.instance.props.autocompletes.commands) if (e.instance.props.autocompletes.commands[i].alias) e.instance.props.autocompletes.commands[i] = null; + e.instance.props.autocompletes.commands = e.instance.props.autocompletes.commands.filter(n => n); + let currentLastWord = e.instance._editorRef.getCurrentWord().word; + let commandAliases = BDFDB.ObjectUtils.filter(this.aliases, key => key.startsWith("/"), true); + if (currentLastWord) for (let word in commandAliases) { + if (e.instance.props.autocompletes.commands.length >= BDFDB.DiscordConstants.MAX_AUTOCOMPLETE_RESULTS) break; + let aliasdata = commandAliases[word]; + let command = {command: word.slice(1), description: aliasdata.replace, alias:true}; + if (!aliasdata.regex && aliasdata.autoc) { + if (aliasdata.exact) { + if (aliasdata.case && word.indexOf(currentLastWord) == 0) e.instance.props.autocompletes.commands.push(command); + else if (!aliasdata.case && word.toLowerCase().indexOf(currentLastWord.toLowerCase()) == 0) e.instance.props.autocompletes.commands.push(command); + } + else { + if (aliasdata.case && word.indexOf(currentLastWord) > -1) e.instance.props.autocompletes.commands.push(command); + else if (!aliasdata.case && word.toLowerCase().indexOf(currentLastWord.toLowerCase()) > -1) e.instance.props.autocompletes.commands.push(command); + } + } + } + } + } + else { if (!BDFDB.ModuleUtils.isPatched(this, e.instance, "handleSubmit")) BDFDB.ModuleUtils.patch(this, e.instance, "handleSubmit", {before: e2 => { let messageData = this.formatText(e2.methodArguments[0]); if (messageData) { @@ -347,44 +375,6 @@ class ChatAliases { } }}, true); } - if (e.node) { - let textarea = e.node.querySelector("textarea"); - if (!textarea) return; - let settings = BDFDB.DataUtils.get(this, "settings"); - BDFDB.ListenerUtils.add(this, textarea, "keydown", event => { - let autocompletemenu = textarea.parentElement.querySelector(BDFDB.dotCN.autocomplete); - if (autocompletemenu && (event.which == 9 || event.which == 13)) { - if (BDFDB.DOMUtils.containsClass(autocompletemenu.querySelector(BDFDB.dotCN.autocompleteselected).parentElement, "autocompleteAliasesRow")) { - BDFDB.ListenerUtils.stopEvent(event); - this.swapWordWithAlias(textarea); - } - } - else if (autocompletemenu && (event.which == 38 || event.which == 40)) { - let autocompleteitems = autocompletemenu.querySelectorAll(BDFDB.dotCN.autocompleteselectable + ":not(.autocompleteAliasesSelector)"); - let selected = autocompletemenu.querySelector(BDFDB.dotCN.autocompleteselected); - if (BDFDB.DOMUtils.containsClass(selected, "autocompleteAliasesSelector") || autocompleteitems[event.which == 38 ? 0 : (autocompleteitems.length-1)] == selected) { - BDFDB.ListenerUtils.stopEvent(event); - let next = this.getNextSelection(autocompletemenu, null, event.which == 38 ? false : true); - BDFDB.DOMUtils.removeClass(selected, BDFDB.disCN.autocompleteselected); - BDFDB.DOMUtils.addClass(selected, BDFDB.disCN.autocompleteselector); - BDFDB.DOMUtils.addClass(next, BDFDB.disCN.autocompleteselected); - } - } - else if (textarea.value && !event.shiftKey && event.which == 13 && !autocompletemenu && textarea.value.indexOf("s/") != 0) { - this.format = true; - textarea.dispatchEvent(new Event("input")); - } - else if (!event.ctrlKey && event.which != 16 && settings.addAutoComplete && textarea.selectionStart == textarea.selectionEnd && textarea.selectionEnd == textarea.value.length) { - BDFDB.TimeUtils.clear(textarea.ChatAliasAutocompleteTimeout); - textarea.ChatAliasAutocompleteTimeout = BDFDB.TimeUtils.timeout(() => {this.addAutoCompleteMenu(textarea);},100); - } - - if (!event.ctrlKey && event.which != 38 && event.which != 40 && !(event.which == 39 && textarea.selectionStart == textarea.selectionEnd && textarea.selectionEnd == textarea.value.length)) BDFDB.DOMUtils.remove(".autocompleteAliases", ".autocompleteAliasesRow"); - }); - BDFDB.ListenerUtils.add(this, textarea, "click", _ => { - if (settings.addAutoComplete && textarea.selectionStart == textarea.selectionEnd && textarea.selectionEnd == textarea.value.length) BDFDB.TimeUtils.timeout(() => {this.addAutoCompleteMenu(textarea);}); - }); - } } } @@ -502,11 +492,11 @@ class ChatAliases { if (result) { replaced = true; let replace = aliasdata.file ? "" : BDFDB.StringUtils.insertNRST(aliasdata.replace); - if (result.length > 1) for (var i = 1; i < result.length; i++) replace = replace.replace(new RegExp("\\\\" + i + "|\\$" + i, "g"), result[i]); + if (result.length > 1) for (let i = 1; i < result.length; i++) replace = replace.replace(new RegExp("\\\\" + i + "|\\$" + i, "g"), result[i]); tempstring2 += tempstring1.slice(0, result.index + result[0].length).replace(result[0], replace); tempstring1 = tempstring1.slice(result.index + result[0].length); if (aliasdata.file && typeof aliasdata.filedata == "string") { - var filedata = JSON.parse(aliasdata.filedata); + let filedata = JSON.parse(aliasdata.filedata); files.push(new File([Uint8Array.from(atob(filedata.data), c => c.charCodeAt(0))], filedata.name, {type:filedata.type})); } if (aliasdata.regex && regstring.indexOf("^") == 0) result = null; @@ -522,62 +512,85 @@ class ChatAliases { } openAddModal (wordvalue) { - let chataliasesAddModal = BDFDB.DOMUtils.create(this.chataliasesAddModalMarkup); - let wordvalueinput = chataliasesAddModal.querySelector("#input-wordvalue"); - let replacevalueinput = chataliasesAddModal.querySelector("#input-replacevalue"); - let addbutton = chataliasesAddModal.querySelector(".btn-add"); - - wordvalueinput.value = wordvalue || ""; - - BDFDB.appendModal(chataliasesAddModal); - - let checkInputs = () => { - let validinputs = [wordvalueinput, replacevalueinput]; - let invalidinputs = []; - let type = ""; - if (!wordvalueinput.value.trim()) { - BDFDB.ArrayUtils.remove(validinputs, wordvalueinput); - invalidinputs.push(wordvalueinput); - type += "Wordvalue"; - } - if (!replacevalueinput.value.trim()) { - BDFDB.ArrayUtils.remove(validinputs, replacevalueinput); - invalidinputs.push(replacevalueinput); - type += ((type ? " and " : "") + "Replacevalue"); - } - if (type) addDisabledTooltip(invalidinputs, type); - else { - addbutton.disabled = false; - addbutton.style.removeProperty("pointer-events"); - BDFDB.DOMUtils.remove(".chataliases-disabled-tooltip"); - } - BDFDB.DOMUtils.removeClass(validinputs, "invalid"); + let values = { + wordvalue, + replacevalue: "" }; - let addDisabledTooltip = (invalidinputs, type) => { - BDFDB.DOMUtils.remove(".chataliases-disabled-tooltip"); - addbutton.disabled = true; - BDFDB.DOMUtils.addClass(invalidinputs, "invalid"); - addbutton.style.setProperty("pointer-events", "none", "important"); - BDFDB.TooltipUtils.create(addbutton, "Choose a " + type, {type: "right", color: "red", selector: "chataliases-disabled-tooltip"}); + BDFDB.ModalUtils.open(this, { + size: "MEDIUM", + header: "Add to ChatAliases", + subheader: "", + children: [ + this.createInputs(values), + BDFDB.ArrayUtils.remove(Object.keys(this.defaults.configs), "file").map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { + type: "Switch", + className: BDFDB.disCN.marginbottom8 + " input-config" + key, + label: this.defaults.configs[key].description, + value: this.defaults.configs[key].value + })) + ].flat(10).filter(n => n), + buttons: [{ + key: "ADDBUTTON", + disabled: !Object.keys(values).every(valuename => values[valuename]), + contents: BDFDB.LanguageUtils.LanguageStrings.ADD, + color: "BRAND", + close: true, + click: modal => { + let configs = {}; + for (let key in this.defaults.configs) { + let configinput = modal.querySelector(`.input-config${key} ${BDFDB.dotCN.switchinner}`); + if (configinput) configs[key] = configinput.checked; + } + this.saveWord(values.wordvalue, values.replacevalue, modal.querySelector(".input-replacevalue input[type='file']"), configs); + } + }] + }); + } + + createInputs (values) { + return [{title:"Replace:", type:"", error:"Choose a Wordvalue", valuename:"wordvalue"}, {title:"With:", type:"file", error:"Choose a Replacevalue", valuename:"replacevalue"}].map(inputdata => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormItem, { + title: inputdata.title, + className: BDFDB.disCN.marginbottom8 + " input-" + inputdata.valuename, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, { + type: inputdata.type, + useFilepath: inputdata.type == "file", + value: values[inputdata.valuename], + placeholder: values[inputdata.valuename], + autoFocus: inputdata.valuename == "replacevalue", + errorMessage: !values[inputdata.valuename] && inputdata.error, + onChange: (value, instance) => { + values[inputdata.valuename] = value.trim(); + if (values[inputdata.valuename]) delete instance.props.errorMessage; + else instance.props.errorMessage = inputdata.error; + let addbuttonins = BDFDB.ReactUtils.findOwner(BDFDB.ReactUtils.findOwner(instance, {name:["BDFDB_Modal", "BDFDB_SettingsPanel"], up:true}), {key:"ADDBUTTON"}); + if (addbuttonins) { + addbuttonins.props.disabled = !Object.keys(values).every(valuename => values[valuename]); + BDFDB.ReactUtils.forceUpdate(addbuttonins); + } + } + }) + })); + } + + saveWord (wordvalue, replacevalue, fileselection, configs = BDFDB.DataUtils.get(this, "configs")) { + if (!wordvalue || !replacevalue || !fileselection) return; + var filedata = null; + if (fileselection.files && fileselection.files[0] && BDFDB.LibraryRequires.fs.existsSync(replacevalue)) { + filedata = JSON.stringify({ + data: BDFDB.LibraryRequires.fs.readFileSync(replacevalue).toString("base64"), + name: fileselection.files[0].name, + type: fileselection.files[0].type + }); + } + this.aliases[wordvalue] = { + replace: replacevalue, + filedata: filedata, + case: configs.case, + exact: wordvalue.indexOf(" ") > -1 ? false : configs.exact, + autoc: configs.regex ? false : configs.autoc, + regex: configs.regex, + file: filedata != null }; - wordvalueinput.addEventListener("input", checkInputs); - replacevalueinput.addEventListener("input", checkInputs); - - BDFDB.ListenerUtils.addToChildren(chataliasesAddModal, "click", BDFDB.dotCNC.backdrop + BDFDB.dotCNC.modalclose + ".btn-add", () => { - BDFDB.DOMUtils.remove(".chataliases-disabled-tooltip"); - }); - - addbutton.addEventListener("click", e => { - let configs = {}; - for (let key in this.defaults.configs) { - let configinput = chataliasesAddModal.querySelector("#input-config" + key); - if (configinput) configs[key] = configinput.checked; - } - this.saveWord(wordvalueinput.value.trim(), replacevalueinput.value.trim(), chataliasesAddModal.querySelector("#input-file"), configs); - BDFDB.DataUtils.save(this.aliases, this, "words"); - }); - wordvalueinput.focus(); - - BDFDB.TimeUtils.timeout(checkInputs, 500); + BDFDB.DataUtils.save(this.aliases, this, "words"); } }