diff --git a/Library/0BDFDB.plugin.js b/Library/0BDFDB.plugin.js index 9f22c16fc0..ebc9c1cee0 100644 --- a/Library/0BDFDB.plugin.js +++ b/Library/0BDFDB.plugin.js @@ -7173,6 +7173,7 @@ module.exports = (_ => { onColorChange: color => { this.handleChange(!color ? "" : (this.props.mode == "comp" ? BDFDB.ColorUtils.convert(color, "RGBCOMP").slice(0, 3).join(",") : (this.props.noAlpha ? BDFDB.ColorUtils.convert(color, "RGB") : color))); }, + ref: this.props.controlsRef, pickerConfig: {gradient: false, alpha: this.props.mode != "comp" && !this.props.noAlpha} }) }) : null, @@ -7180,7 +7181,8 @@ module.exports = (_ => { filter: this.props.filter, mode: this.props.mode, useFilePath: this.props.useFilePath, - searchFolders: this.props.searchFolders + searchFolders: this.props.searchFolders, + ref: this.props.controlsRef }) : null ].flat(10).filter(n => n); @@ -7216,7 +7218,10 @@ module.exports = (_ => { }) : null, inputChildren.length == 1 ? inputChildren[0] : BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex, { align: InternalComponents.LibraryComponents.Flex.Align.CENTER, - children: inputChildren.map((child, i) => i != 0 ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, {shrink: 0, children: child}) : child) + children: inputChildren.map((child, i) => i != 0 ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.Flex.Child, { + shrink: 0, + children: child + }) : child) }), this.props.errorMessage ? BDFDB.ReactUtils.createElement(InternalComponents.LibraryComponents.TextElement, { className: BDFDB.disCN.carderror, diff --git a/Plugins/ChatAliases/ChatAliases.plugin.js b/Plugins/ChatAliases/ChatAliases.plugin.js index 70d0fc4408..5b69856ba4 100644 --- a/Plugins/ChatAliases/ChatAliases.plugin.js +++ b/Plugins/ChatAliases/ChatAliases.plugin.js @@ -18,8 +18,8 @@ module.exports = (_ => { "description": "Allow the user to configure their own chat-aliases which will automatically be replaced before the message is being sent" }, "changeLog": { - "fixed": { - "New Aliases": "You can add new Aliases again" + "improved": { + "Canary Changes": "Preparing Plugins for the changes that are already done on Discord Canary" } } }; @@ -267,11 +267,11 @@ module.exports = (_ => { BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { type: "Button", label: "Pick a Word Value and Replacement Value:", - key: "ADDBUTTON", - disabled: !Object.keys(values).every(valuename => values[valuename]), + disabled: !Object.keys(values).every(valueName => values[valueName]), children: BDFDB.LanguageUtils.LanguageStrings.ADD, + ref: instance => {if (instance) values.addButton = instance;}, onClick: _ => { - this.saveWord(values.wordValue, values.replaceValue, settingsPanel.props._node.querySelector(".input-replacevalue input[type='file']")); + this.saveWord(values); BDFDB.PluginUtils.refreshSettingsPanel(this, settingsPanel, collapseStates); } }), @@ -502,36 +502,30 @@ module.exports = (_ => { } openAddModal (wordValue) { - let values = { - wordValue, - replaceValue: "" - }; + let values = {wordValue, replaceValue: ""}; + let configs = BDFDB.ObjectUtils.map(BDFDB.ObjectUtils.filter(this.defaults.configs, key => key != "file", true), n => n.value); + BDFDB.ModalUtils.open(this, { size: "MEDIUM", header: BDFDB.LanguageUtils.LibraryStringsFormat("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, { + Object.keys(configs).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { type: "Switch", - className: "input-config" + key, label: this.defaults.configs[key].description, - value: this.defaults.configs[key].value + value: configs[key], + onChange: value => {configs[key] = value;} })) ].flat(10).filter(n => n), buttons: [{ - key: "ADDBUTTON", - disabled: !Object.keys(values).every(valuename => values[valuename]), + disabled: !Object.keys(values).every(valueName => values[valueName]), contents: BDFDB.LanguageUtils.LanguageStrings.ADD, color: "BRAND", close: true, - onClick: 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); + ref: instance => {if (instance) values.addButton = instance;}, + onClick: _ => { + this.saveWord(values, configs); this.forceUpdateAll(); } }] @@ -552,11 +546,8 @@ module.exports = (_ => { if (!values.wordValue) instance.props.errorMessage = "Choose a Word Value"; else if (aliases[values.wordValue]) instance.props.errorMessage = "Word Value already used, saving will overwrite old Alias"; else delete instance.props.errorMessage; - 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); - } + values.addButton.props.disabled = !Object.keys(values).every(valueName => values[valueName]); + BDFDB.ReactUtils.forceUpdate(values.addButton); } }) }), @@ -564,44 +555,40 @@ module.exports = (_ => { title: "With:", className: BDFDB.disCN.marginbottom8, children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, { - className: "input-replacevalue", type: "file", useFilePath: true, value: values.replaceValue, placeholder: values.replaceValue, autoFocus: true, errorMessage: !values.replaceValue && "Choose a Replacement Value", + controlsRef: instance => {if (instance) values.fileSelection = instance;}, onChange: (value, instance) => { values.replaceValue = value.trim(); if (!values.replaceValue) instance.props.errorMessage = "Choose a Replacement Value"; else delete instance.props.errorMessage; - 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); - } + values.addButton.props.disabled = !Object.keys(values).every(valueName => values[valueName]); + BDFDB.ReactUtils.forceUpdate(values.addButton); } }) }) ]; } - saveWord (wordValue, replaceValue, fileSelection, aliasConfigs = configs) { - console.log(wordValue, replaceValue, fileSelection); - if (!wordValue || !replaceValue || !fileSelection) return; + saveWord (values, aliasConfigs = configs) { + if (!values.wordValue || !values.replaceValue || !values.fileSelection) return; let filedata = null; - if (fileSelection.files && fileSelection.files[0] && BDFDB.LibraryRequires.fs.existsSync(replaceValue)) { + if (values.fileSelection.files && values.fileSelection.files[0] && BDFDB.LibraryRequires.fs.existsSync(values.replaceValue)) { filedata = JSON.stringify({ - data: BDFDB.LibraryRequires.fs.readFileSync(replaceValue).toString("base64"), - name: fileSelection.files[0].name, - type: fileSelection.files[0].type + data: BDFDB.LibraryRequires.fs.readFileSync(values.replaceValue).toString("base64"), + name: values.fileSelection.files[0].name, + type: values.fileSelection.files[0].type }); } - aliases[wordValue] = { - replace: replaceValue, + aliases[values.wordValue] = { + replace: values.replaceValue, filedata: filedata, case: aliasConfigs.case, - exact: wordValue.indexOf(" ") > -1 ? false : aliasConfigs.exact, + exact: values.wordValue.indexOf(" ") > -1 ? false : aliasConfigs.exact, autoc: aliasConfigs.regex ? false : aliasConfigs.autoc, regex: aliasConfigs.regex, file: filedata != null diff --git a/Plugins/ChatFilter/ChatFilter.plugin.js b/Plugins/ChatFilter/ChatFilter.plugin.js index 600a03d0b9..033548940b 100644 --- a/Plugins/ChatFilter/ChatFilter.plugin.js +++ b/Plugins/ChatFilter/ChatFilter.plugin.js @@ -14,12 +14,12 @@ module.exports = (_ => { "info": { "name": "ChatFilter", "author": "DevilBro", - "version": "3.4.8", + "version": "3.4.9", "description": "Allows the user to censor Words or block complete Messages/Statuses" }, "changeLog": { "improved": { - "Status Option": "Plugin now also checks custom statuses, can be disabled" + "Canary Changes": "Preparing Plugins for the changes that are already done on Discord Canary" } } }; @@ -155,9 +155,9 @@ module.exports = (_ => { BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { type: "Button", label: "Pick a Word Value and Replacement Value:", - key: "ADDBUTTON", disabled: !Object.keys(values).every(valuename => values[valuename]), children: BDFDB.LanguageUtils.LanguageStrings.ADD, + ref: instance => {if (instance) values.addButton = instance;}, onClick: _ => { this.saveWord(values); BDFDB.PluginUtils.refreshSettingsPanel(this, settingsPanel, collapseStates); @@ -508,32 +508,29 @@ module.exports = (_ => { openAddModal (wordValue) { let values = {wordValue, replaceValue: "", choice: "blocked"}; + let configs = BDFDB.ObjectUtils.map(this.defaults.configs, n => n.value); + BDFDB.ModalUtils.open(this, { size: "MEDIUM", header: BDFDB.LanguageUtils.LibraryStringsFormat("add_to", "ChatFilter"), subHeader: "", children: [ this.createInputs(values), - BDFDB.ArrayUtils.remove(Object.keys(this.defaults.configs), "file").map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { + Object.keys(configs).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { type: "Switch", - className: "input-config" + key, label: this.defaults.configs[key].description, - value: this.defaults.configs[key].value + value: configs[key], + onChange: value => {configs[key] = value;} })) ].flat(10).filter(n => n), buttons: [{ - key: "ADDBUTTON", disabled: !values.wordValue, contents: BDFDB.LanguageUtils.LanguageStrings.ADD, color: "BRAND", close: true, - onClick: modal => { - let newConfigs = {}; - for (let key in this.defaults.configs) { - let configInput = modal.querySelector(`.input-config${key} ${BDFDB.dotCN.switchinner}`); - if (configInput) newConfigs[key] = configInput.checked; - } - this.saveWord(values, newConfigs); + ref: instance => {if (instance) values.addButton = instance;}, + onClick: _ => { + this.saveWord(values, configs); this.forceUpdateAll(); } }] @@ -541,25 +538,23 @@ module.exports = (_ => { } createInputs (values) { + let wordValueInput; return [ BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.FormComponents.FormItem, { title: "Block/Censor:", className: BDFDB.disCN.marginbottom8, children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextInput, { - key: "WORDVALUE", value: values.wordValue, placeholder: values.wordValue, errorMessage: !values.wordValue && "Choose a Word Value" || words[values.choice][values.wordValue] && `Word Value already used, saving will overwrite old ${values.choice} Word`, + ref: instance => {if (instance) wordValueInput = instance;}, onChange: (value, instance) => { values.wordValue = value.trim(); if (!values.wordValue) instance.props.errorMessage = "Choose a Word Value"; else if (words[values.choice][values.wordValue]) instance.props.errorMessage = `Word Value already used, saving will overwrite old ${values.choice} word`; else delete instance.props.errorMessage; - let addButtonIns = BDFDB.ReactUtils.findOwner(BDFDB.ReactUtils.findOwner(instance, {name: ["BDFDB_Modal", "BDFDB_SettingsPanel"], up: true}), {key: "ADDBUTTON"}); - if (addButtonIns) { - addButtonIns.props.disabled = !values.wordValue; - BDFDB.ReactUtils.forceUpdate(addButtonIns); - } + values.addButton.props.disabled = !values.wordValue; + BDFDB.ReactUtils.forceUpdate(values.addButton); } }) }), @@ -570,24 +565,19 @@ module.exports = (_ => { value: values.replaceValue, placeholder: values.replaceValue, autoFocus: true, - onChange: (value, instance) => { - values.replaceValue = value.trim(); - } + onChange: value => {values.replaceValue = value;} }) }), BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.RadioGroup, { className: BDFDB.disCN.marginbottom8, value: values.choice, options: [{value: "blocked", name: "Block"}, {value: "censored", name: "Censor"}], - onChange: (value, instance) => { - values.choice = value.value; - let wordValueInputIns = BDFDB.ReactUtils.findOwner(BDFDB.ReactUtils.findOwner(instance, {name: ["BDFDB_Modal", "BDFDB_SettingsPanel"], up: true}), {key: "WORDVALUE"}); - if (wordValueInputIns) { - if (!values.wordValue) wordValueInputIns.props.errorMessage = "Choose a Word Value"; - else if (words[values.choice][values.wordValue]) wordValueInputIns.props.errorMessage = `Word Value already used, saving will overwrite old ${values.choice} Word`; - else delete wordValueInputIns.props.errorMessage; - BDFDB.ReactUtils.forceUpdate(wordValueInputIns); - } + onChange: valueObj => { + values.choice = valueObj.value; + if (!values.wordValue) wordValueInput.props.errorMessage = "Choose a Word Value"; + else if (words[values.choice][values.wordValue]) wordValueInput.props.errorMessage = `Word Value already used, saving will overwrite old ${values.choice} Word`; + else delete wordValueInput.props.errorMessage; + BDFDB.ReactUtils.forceUpdate(wordValueInput); } }) ]; @@ -595,8 +585,6 @@ module.exports = (_ => { saveWord (values, wordConfigs = configs) { if (!values.wordValue || !values.choice) return; - values.wordValue = values.wordValue.trim(); - values.replaceValue = values.replaceValue.trim(); if (!BDFDB.ObjectUtils.is(words[values.choice])) words[values.choice] = {}; words[values.choice][values.wordValue] = { replace: values.replaceValue, diff --git a/Plugins/SpotifyControls/SpotifyControls.plugin.js b/Plugins/SpotifyControls/SpotifyControls.plugin.js index 8edcd843e8..9be9928d70 100644 --- a/Plugins/SpotifyControls/SpotifyControls.plugin.js +++ b/Plugins/SpotifyControls/SpotifyControls.plugin.js @@ -631,7 +631,7 @@ module.exports = (_ => { contents: BDFDB.LanguageUtils.LanguageStrings.CONNECT, color: "BRAND", close: true, - onClick: modal => { + onClick: _ => { BDFDB.LibraryModules.UserSettingsUtils.open(BDFDB.DiscordConstants.UserSettingsSections.CONNECTIONS) } }] diff --git a/Plugins/ThemeSettings/ThemeSettings.plugin.js b/Plugins/ThemeSettings/ThemeSettings.plugin.js index 1c0975363e..fd89ba37ca 100644 --- a/Plugins/ThemeSettings/ThemeSettings.plugin.js +++ b/Plugins/ThemeSettings/ThemeSettings.plugin.js @@ -14,12 +14,12 @@ module.exports = (_ => { "info": { "name": "ThemeSettings", "author": "DevilBro", - "version": "1.3.0", + "version": "1.3.1", "description": "Allow you to change Theme Variables within BetterDiscord. Adds a Settings button (similar to Plugins) to customizable Themes in your Themes Page" }, "changeLog": { - "added": { - "Imports": "You can now enable/disable imports in the settings" + "improved": { + "Canary Changes": "Preparing Plugins for the changes that are already done on Discord Canary" } } }; @@ -97,6 +97,7 @@ module.exports = (_ => { let vars = this.getThemeVars(css); if (imports.length || vars.length) { let open = _ => { + let refs = {imports: {}, inputs: {}}; BDFDB.ModalUtils.open(this, { header: `${addon.name} ${BDFDB.LanguageUtils.LanguageStrings.SETTINGS}`, subHeader: "", @@ -105,18 +106,20 @@ module.exports = (_ => { contentClassName: BDFDB.disCN._repomodalsettings, footerClassName: BDFDB.disCN._repomodalfooter, size: "MEDIUM", - children: this.createThemeInputs(addon, imports, vars), - buttons: [{contents: BDFDB.LanguageUtils.LanguageStrings.SAVE, color: "BRAND", onClick: modal => {this.updateTheme(modal, addon);}}] + children: this.createThemeInputs(refs, addon, imports, vars), + buttons: [{ + contents: BDFDB.LanguageUtils.LanguageStrings.SAVE, + color: "BRAND", + onClick: _ => {this.updateTheme(refs, addon);} + }] }); + console.log(refs); }; if (isBeta) { let controls = card.querySelector("." + BDFDB.disCN._repofooter.split(" ")[0] + " " + BDFDB.dotCN._repocontrols); let settingsButton = document.createElement("button"); settingsButton.className = BDFDB.DOMUtils.formatClassName(BDFDB.disCN._repobutton, BDFDB.disCN._repocontrolsbutton, "theme-settings-button"); - settingsButton.appendChild(BDFDB.DOMUtils.create(` - - - `)); + settingsButton.appendChild(BDFDB.DOMUtils.create(``)); controls.insertBefore(settingsButton, controls.firstElementChild); settingsButton.addEventListener("click", open); settingsButton.addEventListener("mouseenter", _ => { @@ -143,40 +146,45 @@ module.exports = (_ => { } } - updateTheme (card, addon) { + updateTheme (refs, addon) { let path = BDFDB.LibraryRequires.path.join(dir, addon.filename); let css = BDFDB.LibraryRequires.fs.readFileSync(path).toString(); if (css) { let amount = 0; - for (let input of card.querySelectorAll(BDFDB.dotCN.switchinner)) { - let oldValue = input.getAttribute("oldvalue"); - let newValue = input.checked; + for (let i in refs.imports) { + let input = refs.imports[i]; + let oldValue = input.props.oldValue; + let newValue = input.props.value; + console.log(oldValue, newValue); if (newValue.toString() != oldValue.toString()) { - let importUrl = input.getAttribute("name"); + let importUrl = input.props.name; if (newValue) css = css.replace(new RegExp(`\\n${BDFDB.StringUtils.regEscape("/* @import url(" + importUrl + "); */")}`, "g"), `\n@import url(${importUrl});`); else css = css.replace(new RegExp(`\\n${BDFDB.StringUtils.regEscape("@import url(" + importUrl + ");")}`, "g"), `\n/* @import url(${importUrl}); */`); - input.setAttribute("oldvalue", newValue); + input.props.oldValue = newValue; amount++; } } - for (let input of card.querySelectorAll(BDFDB.dotCN.input)) { - let oldValue = input.getAttribute("oldvalue"); - let newValue = input.value; + for (let i in refs.inputs) { + let input = refs.inputs[i]; + let oldValue = input.props.oldValue; + let newValue = input.props.value; + console.log(oldValue, newValue); if (newValue && newValue.trim() && newValue != oldValue) { - let varName = input.getAttribute("name"); + let varName = input.props.name; css = css.replace(new RegExp(`--${BDFDB.StringUtils.regEscape(varName)}(\\s*):(\\s*)${BDFDB.StringUtils.regEscape(oldValue)}`,"g"), `--${varName}$1: $2${newValue}`); - input.setAttribute("oldvalue", newValue); - input.setAttribute("placeholder", newValue); + input.props.oldValue = newValue; + input.props.placeholder = newValue; amount++; } } if (amount > 0) { + BDFDB.ReactUtils.forceUpdate(BDFDB.ObjectUtils.toArray(refs.imports), BDFDB.ObjectUtils.toArray(refs.inputs)); BDFDB.LibraryRequires.fs.writeFileSync(path, css); - BDFDB.NotificationUtils.toast(`Updated ${amount} variable${amount == 1 ? "" : "s"} in ${addon.filename}`, {type: "success"}); + BDFDB.NotificationUtils.toast(`Updated ${amount} Variable${amount == 1 ? "" : "s"} in '${addon.filename}'`, {type: "success"}); } - else BDFDB.NotificationUtils.toast(`There are no changed variables to be updated in ${addon.filename}`, {type: "warning"}); + else BDFDB.NotificationUtils.toast(`There are no changed Variables to be updated in '${addon.filename}'`, {type: "warning"}); } - else BDFDB.NotificationUtils.toast(`Could not find themefile: ${addon.filename}`, {type: "danger"}); + else BDFDB.NotificationUtils.toast(`Could not find Theme File '${addon.filename}'`, {type: "danger"}); } getThemeImports (css) { @@ -196,27 +204,30 @@ module.exports = (_ => { return []; } - createThemeInputs (theme, imports, vars) { + createThemeInputs (refs, theme, imports, vars) { let settingsItems = []; if (imports.length) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, { title: "Imports:", dividerBottom: vars.length, - children: imports.map(impo => { + children: imports.map((impo, i) => { let name = impo[0].split("/").pop().replace(/"/g, ""); return BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { type: "Switch", margin: 8, + childProps: { + ref: instance => {if (instance) refs.imports[i] = instance;} + }, label: name[0].toUpperCase() + name.slice(1), note: impo[0].replace(/"/g, ""), name: impo[0], value: impo[1], - oldvalue: impo[1].toString() + oldValue: impo[1].toString() }); }) })); let varInputs = []; - for (let varStr of vars) { - varStr = varStr.split(":"); + for (let i in vars) { + let varStr = vars[i].split(":"); let varName = varStr.shift().trim(); varStr = varStr.join(":").split(/;[^A-z0-9]|\/\*/); let varValue = varStr.shift().trim(); @@ -243,14 +254,15 @@ module.exports = (_ => { childProps: { type: childType, mode: childMode, - filter: childType == "file" && "image" + filter: childType == "file" && "image", + ref: instance => {if (instance) refs.inputs[i] = instance;} }, label: varName[0].toUpperCase() + varName.slice(1), note: varDescription && varDescription.indexOf("*") == 0 ? varDescription.slice(1) : varDescription, basis: "70%", name: varName, value: varValue, - oldvalue: varValue, + oldValue: varValue, placeholder: varValue })); } diff --git a/Plugins/UserNotes/UserNotes.plugin.js b/Plugins/UserNotes/UserNotes.plugin.js index d0542a693e..db6bf27b32 100644 --- a/Plugins/UserNotes/UserNotes.plugin.js +++ b/Plugins/UserNotes/UserNotes.plugin.js @@ -14,8 +14,13 @@ module.exports = (_ => { "info": { "name": "UserNotes", "author": "DevilBro", - "version": "1.0.5", + "version": "1.0.6", "description": "Allow you to write your own user notes wihtout a character limit" + }, + "changeLog": { + "improved": { + "Canary Changes": "Preparing Plugins for the changes that are already done on Discord Canary" + } } }; @@ -107,6 +112,7 @@ module.exports = (_ => { openNotesModal (user) { let note = BDFDB.DataUtils.load(this, "notes", user.id); + let textarea; BDFDB.ModalUtils.open(this, { size: "LARGE", @@ -117,15 +123,16 @@ module.exports = (_ => { BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TextArea, { value: note, placeholder: note, - autoFocus: true + autoFocus: true, + ref: instance => {if (instance) textarea = instance;} }) ], buttons: [{ contents: BDFDB.LanguageUtils.LanguageStrings.SAVE, color: "BRAND", close: true, - onClick: modal => { - note = modal.querySelector("textarea").value; + onClick: _ => { + note = textarea.props.value; if (note) BDFDB.DataUtils.save(note, this, "notes", user.id); else BDFDB.DataUtils.remove(this, "notes", user.id); }