add toasts
This commit is contained in:
parent
6b517adbe8
commit
2d784b48f4
|
@ -8,7 +8,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { DOM, BdUI, BdMenu, Modals, Reflection } from 'ui';
|
||||
import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts } from 'ui';
|
||||
import BdCss from './styles/index.scss';
|
||||
import { Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, Vendor, WebpackModules, Patcher, MonkeyPatch, ReactComponents, ReactAutoPatcher, DiscordApi } from 'modules';
|
||||
import { ClientLogger as Logger, ClientIPC, Utils } from 'common';
|
||||
|
@ -26,7 +26,7 @@ class BetterDiscord {
|
|||
Logger.log('main', 'BetterDiscord starting');
|
||||
|
||||
this._bd = {
|
||||
DOM, BdUI, BdMenu, Modals, Reflection,
|
||||
DOM, BdUI, BdMenu, Modals, Reflection, Toasts,
|
||||
|
||||
Events, CssEditor, Globals, Settings, Database, Updater,
|
||||
ModuleManager, PluginManager, ThemeManager, ExtModuleManager,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
import { EmoteModule } from 'builtin';
|
||||
import { SettingsSet, SettingsCategory, Setting, SettingsScheme } from 'structs';
|
||||
import { BdMenu, Modals, DOM, Reflection } from 'ui';
|
||||
import { BdMenu, Modals, DOM, Reflection, Toasts } from 'ui';
|
||||
import { Utils, ClientLogger as Logger, ClientIPC, AsyncEventEmitter } from 'common';
|
||||
import Settings from './settings';
|
||||
import ExtModuleManager from './extmodulemanager';
|
||||
|
@ -289,6 +289,27 @@ export default class PluginApi {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toasts
|
||||
*/
|
||||
showToast(message, options = {}) {
|
||||
return Toasts.push(message, options);
|
||||
}
|
||||
showSuccessToast(message, options = {}) {
|
||||
return Toasts.success(message, options);
|
||||
}
|
||||
showInfoToast(message, options = {}) {
|
||||
return Toasts.info(message, options);
|
||||
}
|
||||
showErrorToast(message, options = {}) {
|
||||
return Toasts.error(message, options);
|
||||
}
|
||||
showWarningToast(message, options = {}) {
|
||||
return Toasts.warning(message, options);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emotes
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { Toasts } from 'ui';
|
||||
import { EmoteModule } from 'builtin';
|
||||
import { SettingsSet, SettingUpdatedEvent } from 'structs';
|
||||
import { Utils, FileUtils, ClientLogger as Logger } from 'common';
|
||||
|
@ -28,6 +29,7 @@ export default new class Settings {
|
|||
Logger.log('Settings', [`${set.id}/${category.id}/${setting.id} was changed from`, old_value, 'to', value]);
|
||||
Events.emit('setting-updated', event);
|
||||
Events.emit(`setting-updated-${set.id}_${category.id}_${setting.id}`, event);
|
||||
Toasts.success(`${set.id}/${category.id}/${setting.id} was changed from ${old_value} to ${value}`); // Just for debugging purposes remove in prod
|
||||
});
|
||||
|
||||
set.on('settings-updated', async event => {
|
||||
|
|
|
@ -49,6 +49,30 @@
|
|||
}
|
||||
}
|
||||
|
||||
@keyframes bd-toast-up {
|
||||
0% {
|
||||
transform: translateY(10px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bd-toast-down {
|
||||
0% {
|
||||
transform: translateY(0%);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(10px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bd-fade-out {
|
||||
0% {
|
||||
opacity: 1;
|
||||
|
|
|
@ -13,3 +13,4 @@
|
|||
@import './helpers.scss';
|
||||
@import './misc.scss';
|
||||
@import './emotes.scss';
|
||||
@import './toasts.scss';
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
bd-toasts {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 700px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 100px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
pointer-events: none;
|
||||
z-index: 4000;
|
||||
|
||||
.bd-toast {
|
||||
position: relative;
|
||||
animation: bd-toast-up 300ms ease;
|
||||
background: #36393F;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 0 1px rgba(32,34,37,.6), 0 2px 10px 0 rgba(0,0,0,.2);
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
user-select: text;
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
|
||||
|
||||
&.bd-toast-error {
|
||||
background: #f04747;
|
||||
}
|
||||
|
||||
&.bd-toast-info {
|
||||
background: #4a90e2;
|
||||
}
|
||||
|
||||
&.bd-toast-warning {
|
||||
background: #FFA600;
|
||||
}
|
||||
|
||||
&.bd-toast-success {
|
||||
background: #43b581;
|
||||
}
|
||||
|
||||
&.bd-toast-has-icon {
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-toast-icon {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
bottom: 0;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
svg {
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-toast.bd-toast-closing {
|
||||
animation: bd-toast-down 300ms ease;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import { remote } from 'electron';
|
|||
import DOM from './dom';
|
||||
import Vue from './vue';
|
||||
import AutoManip from './automanip';
|
||||
import { BdSettingsWrapper, BdModals } from './components';
|
||||
import { BdSettingsWrapper, BdModals, BdToasts } from './components';
|
||||
|
||||
export default class {
|
||||
|
||||
|
@ -68,6 +68,13 @@ export default class {
|
|||
DOM.createElement('div', null, 'bd-settings').appendTo(DOM.bdBody);
|
||||
DOM.createElement('div', null, 'bd-modals').appendTo(DOM.bdModals);
|
||||
DOM.createElement('bd-tooltips').appendTo(DOM.bdBody);
|
||||
DOM.createElement('bd-toasts').appendTo(DOM.bdBody);
|
||||
|
||||
const toasts = new Vue({
|
||||
el: 'bd-toasts',
|
||||
components: { BdToasts },
|
||||
template: '<BdToasts/>'
|
||||
});
|
||||
|
||||
this.modals = new Vue({
|
||||
el: '#bd-modals',
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* BetterDiscord Modals Component
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
<template>
|
||||
<bd-toasts>
|
||||
<Toast v-for="(toast, index) in toasts" :message="toast.message" :type="toast.type" :icon="toast.icon" :closing="toast.closing" :key="`${toast.id}`"></Toast>
|
||||
</bd-toasts>
|
||||
</template>
|
||||
<script>
|
||||
// Imports
|
||||
import { Toasts } from 'ui';
|
||||
import { Toast } from './common';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Toast
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
toasts: Toasts.stack
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -14,3 +14,6 @@ export { default as MiExtension } from './materialicons/Extension.vue';
|
|||
export { default as MiError } from './materialicons/Error.vue';
|
||||
export { default as MiDiscord } from './materialicons/Discord.vue';
|
||||
export { default as MiStar } from './materialicons/Star.vue';
|
||||
export { default as MiInfo } from './materialicons/Info.vue';
|
||||
export { default as MiWarning } from './materialicons/Warning.vue';
|
||||
export { default as MiSuccess } from './materialicons/Success.vue';
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* BetterDiscord Modal Component
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
<template>
|
||||
<div :class="['bd-toast', {'bd-toast-has-icon': type != 'basic' || icon}, 'bd-toast-' + type, {'bd-toast-closing': closing}]">
|
||||
<div class="bd-toast-icon" v-if="type != 'basic' || icon">
|
||||
<img v-if="icon" :src="icon" width="20" height="20" />
|
||||
<MiSuccess v-else-if="type == 'success'" size="20" />
|
||||
<MiWarning v-else-if="type == 'warning'" size="20" />
|
||||
<MiInfo v-else-if="type == 'info'" size="20" />
|
||||
<MiError v-else-if="type == 'error'" size="20" />
|
||||
</div>
|
||||
<div class="bd-toast-text">
|
||||
{{message}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Imports
|
||||
import { MiSuccess, MiWarning, MiError, MiInfo } from './MaterialIcon';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
message: String,
|
||||
icon: String,
|
||||
type: {
|
||||
default: "basic",
|
||||
validator: function (value) {
|
||||
return ['success', 'warning', 'error', 'info', 'basic'].indexOf(value) !== -1
|
||||
}
|
||||
},
|
||||
closing: {type: Boolean, default: false}
|
||||
},
|
||||
components: {
|
||||
MiSuccess, MiWarning, MiError, MiInfo
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -4,4 +4,5 @@ export { default as FormButton } from './FormButton.vue';
|
|||
export { default as ButtonGroup } from './ButtonGroup.vue';
|
||||
export { default as Button } from './Button.vue';
|
||||
export { default as Modal } from './Modal.vue';
|
||||
export { default as Toast } from './Toast.vue';
|
||||
export * from './MaterialIcon';
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* BetterDiscord Material Design Icon
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* Material Design Icons
|
||||
* Copyright (c) 2014 Google
|
||||
* Apache 2.0 LICENSE
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
*/
|
||||
|
||||
<template>
|
||||
<span class="bd-material-design-icon">
|
||||
<svg :width="size || 24" :height="size || 24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['size']
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* BetterDiscord Material Design Icon
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* Material Design Icons
|
||||
* Copyright (c) 2014 Google
|
||||
* Apache 2.0 LICENSE
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
*/
|
||||
|
||||
<template>
|
||||
<span class="bd-material-design-icon">
|
||||
<svg :width="size || 24" :height="size || 24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['size']
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* BetterDiscord Material Design Icon
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* Material Design Icons
|
||||
* Copyright (c) 2014 Google
|
||||
* Apache 2.0 LICENSE
|
||||
* https://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
*/
|
||||
|
||||
<template>
|
||||
<span class="bd-material-design-icon">
|
||||
<svg :width="size || 24" :height="size || 24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['size']
|
||||
}
|
||||
</script>
|
|
@ -1,3 +1,4 @@
|
|||
export { default as BdSettingsWrapper } from './BdSettingsWrapper.vue';
|
||||
export { default as BdSettings } from './BdSettings.vue';
|
||||
export { default as BdModals } from './BdModals.vue';
|
||||
export { default as BdToasts } from './BdToasts.vue';
|
||||
|
|
|
@ -130,6 +130,9 @@ export default class DOM {
|
|||
static get bdModals() {
|
||||
return this.getElement('bd-modals') || this.createElement('bd-modals').appendTo(this.bdBody);
|
||||
}
|
||||
static get bdToasts() {
|
||||
return this.getElement('bd-toasts') || this.createElement('bd-toasts').appendTo(this.bdBody);
|
||||
}
|
||||
|
||||
static getElement(e) {
|
||||
if (e instanceof BdNode) return e.element;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* BetterDiscord Modals
|
||||
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||
* All rights reserved.
|
||||
* https://betterdiscord.net
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
export default class Toasts {
|
||||
|
||||
/**
|
||||
* This shows a popup message at the bottom of the screen similar to Android Toasts. This is useful for small user feedback.
|
||||
*
|
||||
* @param {string} message The message to be displayed in the toast
|
||||
* @param {Object} options Options object. Optional parameter.
|
||||
* @param {string} options.type Changes the type of the toast stylistically and semantically. Choices: "basic", "info", "success", "error", "warning". Default: "basic"
|
||||
* @param {string} options.icon URL to custom icon to show in the toast. Having this overrides the default icon for the toast type.
|
||||
* @param {number} options.timeout Adjusts the time (in ms) the toast should be shown for before disappearing automatically. Default: 3000
|
||||
* @returns {Promise} This promise resolves when the toast is removed from the DOM.
|
||||
*/
|
||||
static async push(message, options = {}) {
|
||||
const {type = "basic", icon, timeout = 3000} = options;
|
||||
const toast = {id: Math.random(), message, type, icon, closing: false};
|
||||
this.stack.push(toast);
|
||||
await new Promise(resolve => setTimeout(resolve, timeout));
|
||||
toast.closing = true;
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
this.stack.splice(this.stack.indexOf(toast), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a shortcut for `type = "success"` in {@link Toasts#push}. The parameters and options are the same.
|
||||
*/
|
||||
static async success(message, options = {}) {
|
||||
options.type = "success";
|
||||
return this.push(message, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a shortcut for `type = "error"` in {@link Toasts#push}. The parameters and options are the same.
|
||||
*/
|
||||
static async error(message, options = {}) {
|
||||
options.type = "error";
|
||||
return this.push(message, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a shortcut for `type = "info"` in {@link Toasts#push}. The parameters and options are the same.
|
||||
*/
|
||||
static async info(message, options = {}) {
|
||||
options.type = "info";
|
||||
return this.push(message, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a shortcut for `type = "warning"` in {@link Toasts#push}. The parameters and options are the same.
|
||||
*/
|
||||
static async warning(message, options = {}) {
|
||||
options.type = "warning";
|
||||
return this.push(message, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of active toasts.
|
||||
*/
|
||||
static get stack() {
|
||||
return this._stack || (this._stack = []);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,5 +3,6 @@ export { default as BdUI } from './bdui';
|
|||
export { default as VueInjector } from './vueinjector';
|
||||
export { default as BdMenu, BdMenuItems } from './bdmenu';
|
||||
export { default as Modals } from './modals';
|
||||
export { default as Toasts } from './toasts';
|
||||
export { default as ProfileBadges } from './profilebadges';
|
||||
export { default as Reflection } from './reflection';
|
||||
|
|
Loading…
Reference in New Issue