Merge branch 'master' into security

This commit is contained in:
Alexei Stukov 2018-08-13 14:38:25 +03:00 committed by GitHub
commit c893216874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 81 additions and 35 deletions

View File

@ -93,6 +93,13 @@
"hint": "When this is enabled you can use Ctrl/Cmd + B to open the BetterDiscord settings menu.", "hint": "When this is enabled you can use Ctrl/Cmd + B to open the BetterDiscord settings menu.",
"value": false, "value": false,
"disabled": false "disabled": false
},
{
"id": "enable-toasts",
"type": "bool",
"text": "Enable Toasts",
"hint": "Allows plugins to show toasts.",
"value": true
} }
] ]
} }
@ -144,7 +151,7 @@
{ {
"id": "security", "id": "security",
"text": "Security and Privacy", "text": "Security and Privacy",
"headertext": "Security Settings", "headertext": "Security and Privacy Settings",
"settings": [ "settings": [
{ {
"id": "default", "id": "default",

View File

@ -18,9 +18,9 @@ import { ClientLogger as Logger } from 'common';
/** /**
* A callback that modifies method logic. This callback is called on each call of the original method and is provided all data about original call. Any of the data can be modified if necessary, but do so wisely. * A callback that modifies method logic. This callback is called on each call of the original method and is provided all data about original call. Any of the data can be modified if necessary, but do so wisely.
* *
* The third argument for the callback will be `undefined` for `before` patches. `originalFunction` for `instead` patches and `returnValue` for `after` patches. * The third argument for the callback will be `undefined` for `before` patches. `originalFunction` for `instead` patches and `returnValue` for `after` patches.
* *
* @callback Patcher~patchCallback * @callback Patcher~patchCallback
* @param {object} thisObject - `this` in the context of the original function. * @param {object} thisObject - `this` in the context of the original function.
* @param {arguments} arguments - The original arguments of the original function. * @param {arguments} arguments - The original arguments of the original function.
@ -42,8 +42,8 @@ export class Patcher {
const patches = []; const patches = [];
for (const patch of this.patches) { for (const patch of this.patches) {
for (const childPatch of patch.children) { for (const childPatch of patch.children) {
if (childPatch.caller === id) patches.push(childPatch); if (childPatch.caller === id) patches.push(childPatch);
} }
} }
return patches; return patches;
} }
@ -135,7 +135,7 @@ export class Patcher {
/** /**
* This method patches onto another function, allowing your code to run beforehand. * This method patches onto another function, allowing your code to run beforehand.
* Using this, you are also able to modify the incoming arguments before the original method is run. * Using this, you are also able to modify the incoming arguments before the original method is run.
* *
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}. * @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}.
* @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype. * @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched * @param {string} functionName - Name of the method to be patched
@ -148,7 +148,7 @@ export class Patcher {
/** /**
* This method patches onto another function, allowing your code to run afterwards. * This method patches onto another function, allowing your code to run afterwards.
* Using this, you are also able to modify the return value, using the return of your code instead. * Using this, you are also able to modify the return value, using the return of your code instead.
* *
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}. * @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}.
* @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype. * @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched * @param {string} functionName - Name of the method to be patched
@ -161,7 +161,7 @@ export class Patcher {
/** /**
* This method patches onto another function, allowing your code to run instead, preventing the running of the original code. * This method patches onto another function, allowing your code to run instead, preventing the running of the original code.
* Using this, you are also able to modify the return value, using the return of your code instead. * Using this, you are also able to modify the return value, using the return of your code instead.
* *
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}. * @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}.
* @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype. * @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched * @param {string} functionName - Name of the method to be patched
@ -175,7 +175,7 @@ export class Patcher {
* This method patches onto another function, allowing your code to run before, instead or after the original function. * This method patches onto another function, allowing your code to run before, instead or after the original function.
* Using this you are able to modify the incoming arguments before the original function is run as well as the return * Using this you are able to modify the incoming arguments before the original function is run as well as the return
* value before the original function actually returns. * value before the original function actually returns.
* *
* @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}. * @param {string} caller - Name of the caller of the patch function. Using this you can undo all patches with the same name using {@link Patcher#unpatchAll}.
* @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype. * @param {object} unresolvedModule - Object with the function to be patched. Can also patch an object's prototype.
* @param {string} functionName - Name of the method to be patched * @param {string} functionName - Name of the method to be patched
@ -201,10 +201,10 @@ export class Patcher {
unpatch: () => { unpatch: () => {
patch.children.splice(patch.children.findIndex(cpatch => cpatch.id === child.id && cpatch.type === type), 1); patch.children.splice(patch.children.findIndex(cpatch => cpatch.id === child.id && cpatch.type === type), 1);
if (patch.children.length <= 0) { if (patch.children.length <= 0) {
const patchNum = this.patches.findIndex(p => p.module == module && p.functionName == functionName); const patchNum = this.patches.findIndex(p => p.module == module && p.functionName == functionName);
this.patches[patchNum].revert(); this.patches[patchNum].revert();
this.patches.splice(patchNum, 1); this.patches.splice(patchNum, 1);
} }
} }
}; };
patch.children.push(child); patch.children.push(child);

View File

@ -330,7 +330,8 @@ export default class PluginApi {
success: this.showSuccessToast.bind(this), success: this.showSuccessToast.bind(this),
error: this.showErrorToast.bind(this), error: this.showErrorToast.bind(this),
info: this.showInfoToast.bind(this), info: this.showInfoToast.bind(this),
warning: this.showWarningToast.bind(this) warning: this.showWarningToast.bind(this),
get enabled() { return Toasts.enabled }
}; };
} }

View File

@ -44,11 +44,14 @@
} }
&.bd-hide-button { &.bd-hide-button {
transition: opacity 0.4s ease-out; animation: bd-fade-out 0.4s ease-out;
opacity: 0;
&.bd-active { &.bd-active {
transition-timing-function: ease-in; animation: bd-fade-in 0.4s ease-in;
}
&:not(.bd-active):not(.bd-animating) {
display: none;
} }
} }

View File

@ -2,7 +2,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
div:first-child { > :first-child {
flex: 1 1 auto; flex: 1 1 auto;
} }
@ -11,6 +11,10 @@
flex-grow: 1; flex-grow: 1;
margin-top: 5px; margin-top: 5px;
> :first-child {
flex: 1 0 auto;
}
.bd-removeCollectionItem { .bd-removeCollectionItem {
width: 20px; width: 20px;
flex: 0 1 auto; flex: 0 1 auto;
@ -18,19 +22,22 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
margin-bottom: 30px;
&:hover {
svg {
fill: #FFF;
}
}
svg { svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
fill: #ccc; fill: #ccc;
} }
&:not(.bd-disabled):hover {
svg {
fill: #fff;
}
}
&.bd-disabled {
opacity: 0.5;
}
} }
} }
@ -41,6 +48,7 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-right: 2px; margin-right: 2px;
margin-top: 10px;
svg { svg {
width: 16px; width: 16px;

View File

@ -9,3 +9,4 @@
@import './files.scss'; @import './files.scss';
@import './guilds.scss'; @import './guilds.scss';
@import './arrays.scss'; @import './arrays.scss';
@import './collections.scss';

View File

@ -65,8 +65,7 @@ export default class ClassNormaliser extends Module {
normalizeElement(element) { normalizeElement(element) {
if (!(element instanceof Element)) return; if (!(element instanceof Element)) return;
if (element.children && element.children.length) this.normalizeElement(element.children[0]);
if (element.nextElementSibling) this.normalizeElement(element.nextElementSibling);
const classes = element.classList; const classes = element.classList;
for (let c = 0, clen = classes.length; c < clen; c++) { for (let c = 0, clen = classes.length; c < clen; c++) {
if (!randClass.test(classes[c])) continue; if (!randClass.test(classes[c])) continue;
@ -74,6 +73,10 @@ export default class ClassNormaliser extends Module {
const newClass = match.split('-').map((s, i) => i ? s[0].toUpperCase() + s.slice(1) : s).join(''); const newClass = match.split('-').map((s, i) => i ? s[0].toUpperCase() + s.slice(1) : s).join('');
element.classList.add(`${normalizedPrefix}-${newClass}`); element.classList.add(`${normalizedPrefix}-${newClass}`);
} }
for (let child of element.children) {
this.normalizeElement(child);
}
} }
} }

View File

@ -47,7 +47,7 @@
methods: { methods: {
keyupListener(e) { keyupListener(e) {
if (Modals.stack.length || !this.active || e.which !== 27) return; if (Modals.stack.length || !this.active || e.which !== 27) return;
if (this.$refs.settings.activeIndex !== -1) this.$refs.settings.closeContent(); if (this.$refs.settings.item) this.$refs.settings.closeContent();
else this.active = false; else this.active = false;
e.stopImmediatePropagation(); e.stopImmediatePropagation();
}, },

View File

@ -11,10 +11,10 @@
<template> <template>
<div class="bd-formCollection"> <div class="bd-formCollection">
<div v-for="s in setting.items" class="bd-collectionItem"> <div v-for="s in setting.items" class="bd-collectionItem">
<Setting :setting="s" :key="s.id" /> <Setting :setting="s" :hide-divider="true" :key="s.id" />
<div class="bd-removeCollectionItem" @click="removeItem(s)"><MiMinus/></div> <div class="bd-removeCollectionItem" :class="{'bd-disabled': setting.disabled || setting.min && setting.items.length <= setting.min}" @click="removeItem(s)"><MiMinus/></div>
</div> </div>
<div class="bd-newCollectionItem" @click="addItem"><MiPlus/></div> <div v-if="!setting.disabled && !setting.max || setting.items.length < setting.max" class="bd-newCollectionItem" @click="addItem"><MiPlus/></div>
</div> </div>
</template> </template>
@ -29,9 +29,11 @@
}, },
methods: { methods: {
removeItem(item) { removeItem(item) {
if (this.setting.disabled || this.setting.min && this.setting.items.length <= this.setting.min) return;
this.setting.removeItem(item); this.setting.removeItem(item);
}, },
addItem() { addItem() {
if (this.setting.disabled || this.setting.max && this.setting.items.length >= this.setting.max) return;
this.setting.addItem(); this.setting.addItem();
} }
}, },

View File

@ -26,7 +26,8 @@
<KeyValuePair v-else-if="setting.type === 'kvp'" :setting="setting" /> <KeyValuePair v-else-if="setting.type === 'kvp'" :setting="setting" />
<SecureKeyValuePair v-else-if="setting.type === 'securekvp'" :setting="setting" /> <SecureKeyValuePair v-else-if="setting.type === 'securekvp'" :setting="setting" />
<CustomSetting v-else-if="setting.type === 'custom'" :setting="setting" /> <CustomSetting v-else-if="setting.type === 'custom'" :setting="setting" />
<div class="bd-form-divider"></div>
<div v-if="!hideDivider" class="bd-form-divider"></div>
</div> </div>
</template> </template>
@ -51,7 +52,8 @@
export default { export default {
props: [ props: [
'setting' 'setting',
'hide-divider'
], ],
components: { components: {
BoolSetting, BoolSetting,

View File

@ -8,6 +8,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import { Settings } from 'modules';
let toasts = 0; let toasts = 0;
export default class Toasts { export default class Toasts {
@ -24,6 +26,8 @@ export default class Toasts {
* @returns {Promise} This promise resolves when the toast is removed from the DOM. * @returns {Promise} This promise resolves when the toast is removed from the DOM.
*/ */
static async push(message, options = {}) { static async push(message, options = {}) {
if (!this.enabled) return;
const {type = 'basic', icon, additionalClasses, timeout = 3000} = options; const {type = 'basic', icon, additionalClasses, timeout = 3000} = options;
const toast = {id: toasts++, message, type, icon, additionalClasses, closing: false}; const toast = {id: toasts++, message, type, icon, additionalClasses, closing: false};
this.stack.push(toast); this.stack.push(toast);
@ -72,4 +76,16 @@ export default class Toasts {
return this._stack || (this._stack = []); return this._stack || (this._stack = []);
} }
static get setting() {
return Settings.getSetting('ui', 'default', 'enable-toasts');
}
static get enabled() {
return this.setting.value;
}
static set enabled(enabled) {
this.setting.value = enabled;
}
} }

View File

@ -81,6 +81,8 @@ gulp.task('node-sass-bindings', function () {
]); ]);
}); });
gulp.task('build-release', gulp.parallel('release-package', 'client', 'core', 'sparkplug', 'core-modules', 'index', 'css-editor', gulp.series('dependencies', 'node-sass-bindings')));
gulp.task('release', gulp.series(function () { gulp.task('release', gulp.series(function () {
return del(['release/**/*']); return del(['release/**/*']);
}, gulp.parallel('release-package', 'client', 'core', 'sparkplug', 'core-modules', 'index', 'css-editor', gulp.series('dependencies', 'node-sass-bindings')))); }, 'build-release'));

View File

@ -81,6 +81,7 @@
"build_node-sass": "node scripts/build-node-sass.js", "build_node-sass": "node scripts/build-node-sass.js",
"build_release": "npm run release --prefix client && npm run build --prefix core && npm run release --prefix csseditor", "build_release": "npm run release --prefix client && npm run build --prefix core && npm run release --prefix csseditor",
"package_release": "node scripts/package-release.js", "package_release": "node scripts/package-release.js",
"release": "npm run lint && npm run build_release && gulp release && npm run package_release" "release": "npm run lint && npm run build_release && gulp release && npm run package_release",
"update_release": "npm run build_release && gulp build-release"
} }
} }