diff --git a/client/src/index.js b/client/src/index.js index 04248269..98331530 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -8,13 +8,14 @@ * LICENSE file in the root directory of this source tree. */ -import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts } from 'ui'; +import { DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications } from 'ui'; import BdCss from './styles/index.scss'; import { Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, Vendor, WebpackModules, Patcher, MonkeyPatch, ReactComponents, ReactHelpers, ReactAutoPatcher, DiscordApi, BdWebApi, Connectivity, Cache } from 'modules'; import { ClientLogger as Logger, ClientIPC, Utils } from 'common'; import { BuiltinManager, EmoteModule, ReactDevtoolsModule, VueDevtoolsModule, TrackingProtection, E2EE } from 'builtin'; import electron from 'electron'; import path from 'path'; +import { setTimeout } from 'timers'; const tests = typeof PRODUCTION === 'undefined'; const ignoreExternal = false; @@ -27,7 +28,7 @@ class BetterDiscord { Logger.log('main', 'BetterDiscord starting'); this._bd = { - DOM, BdUI, BdMenu, Modals, Reflection, Toasts, + DOM, BdUI, BdMenu, Modals, Reflection, Toasts, Notifications, Events, CssEditor, Globals, Settings, Database, Updater, ModuleManager, PluginManager, ThemeManager, ExtModuleManager, @@ -90,6 +91,23 @@ class BetterDiscord { Events.emit('ready'); Events.emit('discord-ready'); BuiltinManager.initAll(); + + function showDummyNotif() { // eslint-disable-line no-inner-declarations + Notifications.add('Dummy Notification', [ + { + text: 'Show Again', onClick: function () { + setTimeout(showDummyNotif, 5000); + return true; + } + }, + { + text: 'Ignore', onClick: function () { + return true; + } + } + ]); + } + showDummyNotif(); } catch (err) { Logger.err('main', ['FAILED TO LOAD!', err]); } diff --git a/client/src/styles/partials/generic/badges.scss b/client/src/styles/partials/generic/badges.scss index 5e58fc6e..2b11986d 100644 --- a/client/src/styles/partials/generic/badges.scss +++ b/client/src/styles/partials/generic/badges.scss @@ -40,12 +40,10 @@ .bd-profileBadgeDeveloper, .bd-profileBadgeWebdev, .bd-profileBadgeContributor { - background-image: $logoSmallBw; - filter: brightness(10); + background-image: $logoSmallWw; .theme-light [class*='topSectionNormal-'] .bd-profileBadgesProfileModal > &, // sass-lint:disable-line force-element-nesting class-name-format .theme-light :not(.bd-profileBadgesProfileModal) > & { // sass-lint:disable-line class-name-format background-image: $logoSmallLight; - filter: none; } } diff --git a/client/src/styles/partials/generic/index.scss b/client/src/styles/partials/generic/index.scss index d193ab04..f8472f62 100644 --- a/client/src/styles/partials/generic/index.scss +++ b/client/src/styles/partials/generic/index.scss @@ -12,3 +12,4 @@ @import './layouts'; @import './toasts'; @import './badges'; +@import './notifications'; diff --git a/client/src/styles/partials/generic/notifications.scss b/client/src/styles/partials/generic/notifications.scss new file mode 100644 index 00000000..1722ac58 --- /dev/null +++ b/client/src/styles/partials/generic/notifications.scss @@ -0,0 +1,115 @@ +.bd-notifications { + position: absolute; + right: -300px; + bottom: 50px; + z-index: 900000; + + .bd-notificationContainer { + position: relative; + background: #202225; + width: 280px; + height: 130px; + top: 30px; + border-radius: 5px; + box-shadow: 0 0 20px #202225; + + .bd-notificationHeader { + height: 10px; + justify-content: flex-end; + + .bd-notificationDismissBtn { + cursor: pointer; + opacity: 0; + transform: scaleX(-1); + margin: 8px; + + &:hover { + opacity: 1; + background: rgba(0, 0, 0, .1); + + .bd-materialDesignIcon { + fill: #fff; + } + } + + .bd-materialDesignIcon { + fill: #aeaeae; + display: flex; + height: 20px; + } + } + } + + &:hover { + .bd-notificationDismissBtn { + opacity: 1; + } + } + + .bd-notificationBody { + padding: 10px 25px; + flex-grow: 1; + + .bd-notificationText { + color: #fff; + font-size: 12px; + } + } + + &.bd-active { + animation: bd-notif-slidein 1s forwards; + } + + &.bd-closing { + animation: bd-notif-slideout .5s; + } + } + + .bd-notificationFooter { + height: 20px; + padding: 5px; + justify-content: flex-end; + + .bd-notificationBtn { + cursor: pointer; + height: 10px; + line-height: 10px; + font-size: 14px; + font-weight: 500; + color: #aeaeae; + padding: 5px 10px; + border-radius: 3px; + background: rgba(0, 0, 0, .2); + margin-left: 5px; + + &:hover { + background: rgba(0, 0, 0, .3); + color: #fff; + } + } + } +} + +@keyframes bd-notif-slidein { + 0% { + transform: translatex(0); + } + + 50% { + transform: translatex(-325px); + } + + 100% { + transform: translatex(-315px); + } +} + +@keyframes bd-notif-slideout { + 0% { + transform: translatex(-315px); + } + + 100% { + transform: translatex(0); + } +} diff --git a/client/src/styles/partials/variables/images.scss b/client/src/styles/partials/variables/images.scss index 0af0e367..7a130f45 100644 --- a/client/src/styles/partials/variables/images.scss +++ b/client/src/styles/partials/variables/images.scss @@ -2,6 +2,7 @@ $logoSmallGw: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkltYWdlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUxMiA1MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZGlzcGxheTpub25lO30uc3Qxe2Rpc3BsYXk6aW5saW5lO2ZpbGw6IzAyMDAzNTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LnN0MntmaWxsOiMzRUNDOUU7fS5zdDN7ZmlsbDojRkZGRkZGO308L3N0eWxlPjxnIGlkPSJMYXllcl8yIiBjbGFzcz0ic3QwIj48cmVjdCB4PSItNjQiIHk9Ii0zMiIgY2xhc3M9InN0MSIgd2lkdGg9IjYxOCIgaGVpZ2h0PSI1NzIiLz48L2c+PGcgaWQ9IkxheWVyXzEiIHhtbG5zOnZlY3Rvcm5hdG9yPSJodHRwOi8vdmVjdG9ybmF0b3IuaW8iPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik03MCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3YyMzMuNkM0Mi43LDM5Ny43LDEzNy45LDQ5MywyNTYsNDkzYzI5LjcsMCw1OC02LjEsODMuNi0xN1YzNDEuNWMtMTksMjUuNi00OS4zLDQyLjItODMuNiw0Mi4yYy01Ny42LDAtMTA0LjEtNDYuNS0xMDQuMS0xMDQuMVY0Ni4xYzAtMTMuNy0xMy43LTI3LjMtMjcuMy0yNy4zSDcweiIvPjxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zODcuNCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3Y0Ny4zQzMyOS4zLDc2LjIsMjkzLjksNjYuMywyNTYsNjYuM2MtMjkuOCwwLTU3LjksNi4zLTgzLjYsMTcuM3YxMzQuMmMxOS0yNS42LDQ5LjMtNDIuMiw4My42LTQyLjJjNTcuNiwwLDEwNC4xLDQ2LjUsMTA0LjEsMTA0LjF2MTg2LjJjNjUuMi0zNi40LDEwOS4yLTEwNiwxMDkuMi0xODYuMlY0Ni4xYzAtMTguOC0xMy43LTI3LjMtMjcuMy0yNy4zSDM4Ny40eiIvPjwvZz48L3N2Zz4=); $logoSmallBw: $logoSmallGw; +$logoSmallWw: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkltYWdlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUxMiA1MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZGlzcGxheTpub25lO30uc3Qxe2Rpc3BsYXk6aW5saW5lO2ZpbGw6IzAyMDAzNTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LnN0MntmaWxsOiNGRkZGRkY7fTwvc3R5bGU+PGcgaWQ9IkxheWVyXzIiIGNsYXNzPSJzdDAiPjxyZWN0IHg9Ii02NCIgeT0iLTMyIiBjbGFzcz0ic3QxIiB3aWR0aD0iNjE4IiBoZWlnaHQ9IjU3MiIvPjwvZz48ZyBpZD0iTGF5ZXJfMSIgeG1sbnM6dmVjdG9ybmF0b3I9Imh0dHA6Ly92ZWN0b3JuYXRvci5pbyI+PHBhdGggY2xhc3M9InN0MiIgZD0iTTcwLDE4LjhjLTEzLjcsMC0yNy4zLDEzLjctMjcuMywyNy4zdjIzMy42QzQyLjcsMzk3LjcsMTM3LjksNDkzLDI1Niw0OTNjMjkuNywwLDU4LTYuMSw4My42LTE3VjM0MS41Yy0xOSwyNS42LTQ5LjMsNDIuMi04My42LDQyLjJjLTU3LjYsMC0xMDQuMS00Ni41LTEwNC4xLTEwNC4xVjQ2LjFjMC0xMy43LTEzLjctMjcuMy0yNy4zLTI3LjNINzB6Ii8+PHBhdGggY2xhc3M9InN0MiIgZD0iTTM4Ny40LDE4LjhjLTEzLjcsMC0yNy4zLDEzLjctMjcuMywyNy4zdjQ3LjNDMzI5LjMsNzYuMiwyOTMuOSw2Ni4zLDI1Niw2Ni4zYy0yOS44LDAtNTcuOSw2LjMtODMuNiwxNy4zdjEzNC4yYzE5LTI1LjYsNDkuMy00Mi4yLDgzLjYtNDIuMmM1Ny42LDAsMTA0LjEsNDYuNSwxMDQuMSwxMDQuMXYxODYuMmM2NS4yLTM2LjQsMTA5LjItMTA2LDEwOS4yLTE4Ni4yVjQ2LjFjMC0xOC44LTEzLjctMjcuMy0yNy4zLTI3LjNIMzg3LjR6Ii8+PC9nPjwvc3ZnPg=='); $logoSmallGb: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkltYWdlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUxMiA1MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZGlzcGxheTpub25lO30uc3Qxe2Rpc3BsYXk6aW5saW5lO2ZpbGw6IzAyMDAzNTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LnN0MntmaWxsOiMzRUNDOUU7fS5zdDN7ZmlsbDojMDAwMDAwO308L3N0eWxlPjxnIGlkPSJMYXllcl8yIiBjbGFzcz0ic3QwIj48cmVjdCB4PSItNjQiIHk9Ii0zMiIgY2xhc3M9InN0MSIgd2lkdGg9IjYxOCIgaGVpZ2h0PSI1NzIiLz48L2c+PGcgaWQ9IkxheWVyXzEiIHhtbG5zOnZlY3Rvcm5hdG9yPSJodHRwOi8vdmVjdG9ybmF0b3IuaW8iPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik03MCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3YyMzMuNkM0Mi43LDM5Ny43LDEzNy45LDQ5MywyNTYsNDkzYzI5LjcsMCw1OC02LjEsODMuNi0xN1YzNDEuNWMtMTksMjUuNi00OS4zLDQyLjItODMuNiw0Mi4yYy01Ny42LDAtMTA0LjEtNDYuNS0xMDQuMS0xMDQuMVY0Ni4xYzAtMTMuNy0xMy43LTI3LjMtMjcuMy0yNy4zSDcweiIvPjxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zODcuNCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3Y0Ny4zQzMyOS4zLDc2LjIsMjkzLjksNjYuMywyNTYsNjYuM2MtMjkuOCwwLTU3LjksNi4zLTgzLjYsMTcuM3YxMzQuMmMxOS0yNS42LDQ5LjMtNDIuMiw4My42LTQyLjJjNTcuNiwwLDEwNC4xLDQ2LjUsMTA0LjEsMTA0LjF2MTg2LjJjNjUuMi0zNi40LDEwOS4yLTEwNiwxMDkuMi0xODYuMlY0Ni4xYzAtMTguOC0xMy43LTI3LjMtMjcuMy0yNy4zSDM4Ny40eiIvPjwvZz48L3N2Zz4=); // $logoSmallLight: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FscXVlXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjAwMCAyMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyMDAwIDIwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMzRTgyRTUiIGQ9Ik0xNDAyLjIsNjMxLjdjLTkuNy0zNTMuNC0yODYuMi00OTYtNjQyLjYtNDk2SDY4LjR2NzE0LjFsNDQyLDM5OFY0OTAuN2gyNTdjMjc0LjUsMCwyNzQuNSwzNDQuOSwwLDM0NC45SDU5Ny42djMyOS41aDE2OS44YzI3NC41LDAsMjc0LjUsMzQ0LjgsMCwzNDQuOGgtNjk5djM1NC45aDY5MS4yYzM1Ni4zLDAsNjMyLjgtMTQyLjYsNjQyLjYtNDk2YzAtMTYyLjYtNDQuNS0yODQuMS0xMjIuOS0zNjguNkMxMzU3LjcsOTE1LjgsMTQwMi4yLDc5NC4zLDE0MDIuMiw2MzEuN3oiLz48cGF0aCBmaWxsPSIjYmJiYmJiIiBkPSJNMTI2Mi41LDEzNS4yTDEyNjIuNSwxMzUuMmwtNzYuOCwwYzI2LjYsMTMuMyw1MS43LDI4LjEsNzUsNDQuM2M3MC43LDQ5LjEsMTI2LjEsMTExLjUsMTY0LjYsMTg1LjNjMzkuOSw3Ni42LDYxLjUsMTY1LjYsNjQuMywyNjQuNmwwLDEuMnYxLjJjMCwxNDEuMSwwLDU5Ni4xLDAsNzM3LjF2MS4ybDAsMS4yYy0yLjcsOTktMjQuMywxODgtNjQuMywyNjQuNmMtMzguNSw3My44LTkzLjgsMTM2LjItMTY0LjYsMTg1LjNjLTIyLjYsMTUuNy00Ni45LDMwLjEtNzIuNiw0My4xaDcyLjVjMzQ2LjIsMS45LDY3MS0xNzEuMiw2NzEtNTY3LjlWNzE2LjdDMTkzMy41LDMxMi4yLDE2MDguNywxMzUuMiwxMjYyLjUsMTM1LjJ6Ii8+PC9nPjwvc3ZnPg=='); diff --git a/client/src/ui/bdui.js b/client/src/ui/bdui.js index 4fd07eb2..c57e918e 100644 --- a/client/src/ui/bdui.js +++ b/client/src/ui/bdui.js @@ -12,7 +12,7 @@ import { Events, DiscordApi, Settings } from 'modules'; import { remote } from 'electron'; import DOM from './dom'; import Vue from './vue'; -import { BdSettingsWrapper, BdModals, BdToasts } from './components'; +import { BdSettingsWrapper, BdModals, BdToasts, BdNotifications } from './components'; export default class { @@ -52,6 +52,7 @@ export default class { DOM.createElement('div', null, 'bd-settings').appendTo(DOM.bdBody); DOM.createElement('div', null, 'bd-modals').appendTo(DOM.bdModals); DOM.createElement('div', null, 'bd-toasts').appendTo(DOM.bdToasts); + DOM.createElement('div', null, 'bd-notifications').appendTo(DOM.bdNotifications); DOM.createElement('bd-tooltips').appendTo(DOM.bdBody); this.toasts = new (Vue.extend(BdToasts))({ @@ -66,6 +67,10 @@ export default class { el: '#bd-settings' }); + this.notifications = new (Vue.extend(BdNotifications))({ + el: '#bd-notifications' + }); + return this.vueInstance; } diff --git a/client/src/ui/components/BdNotifications.vue b/client/src/ui/components/BdNotifications.vue new file mode 100644 index 00000000..efeea8a2 --- /dev/null +++ b/client/src/ui/components/BdNotifications.vue @@ -0,0 +1,63 @@ +/** + * BetterDiscord Notifications 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. +*/ + + + + diff --git a/client/src/ui/components/common/MaterialIcon.js b/client/src/ui/components/common/MaterialIcon.js index f5d4b6b3..18355005 100644 --- a/client/src/ui/components/common/MaterialIcon.js +++ b/client/src/ui/components/common/MaterialIcon.js @@ -20,3 +20,4 @@ export { default as MiSuccess } from './materialicons/Success.vue'; export { default as AccountCircle } from './materialicons/AccountCircle.vue'; export { default as MiLock } from './materialicons/Lock.vue'; export { default as MiImagePlus } from './materialicons/ImagePlus.vue'; +export { default as MiArrowLeft } from './materialicons/ArrowLeft.vue'; diff --git a/client/src/ui/components/common/materialicons/ArrowLeft.vue b/client/src/ui/components/common/materialicons/ArrowLeft.vue new file mode 100644 index 00000000..325a2949 --- /dev/null +++ b/client/src/ui/components/common/materialicons/ArrowLeft.vue @@ -0,0 +1,27 @@ +/** + * 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 +*/ + + + diff --git a/client/src/ui/components/index.js b/client/src/ui/components/index.js index 3a22b4d8..60616b7a 100644 --- a/client/src/ui/components/index.js +++ b/client/src/ui/components/index.js @@ -2,3 +2,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'; +export { default as BdNotifications } from './BdNotifications.vue'; diff --git a/client/src/ui/dom.js b/client/src/ui/dom.js index 2428a29c..91d311f1 100644 --- a/client/src/ui/dom.js +++ b/client/src/ui/dom.js @@ -184,9 +184,8 @@ export default class DOM { static get bdThemes() { return this.getElement('bd-themes') || this.createElement('bd-themes').appendTo(this.bdHead) } static get bdTooltips() { return this.getElement('bd-tooltips') || this.createElement('bd-tooltips').appendTo(this.bdBody) } 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 get bdToasts() { return this.getElement('bd-toasts') || this.createElement('bd-toasts').appendTo(this.bdBody) } + static get bdNotifications() { return this.getElement('bd-notifications') || this.createElement('bd-notifications').appendTo(this.bdBody) } static getElement(e) { if (e instanceof BdNode) return e.element; diff --git a/client/src/ui/notifications.js b/client/src/ui/notifications.js new file mode 100644 index 00000000..5d6da771 --- /dev/null +++ b/client/src/ui/notifications.js @@ -0,0 +1,41 @@ +/* + * BetterDiscord Notifications + * 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. +*/ + +import { Events } from 'modules'; + +export default class Notifications { + + /** + * Add a new notification to the stack. + * Notifications should only be used for important things. + * @param {String} text + * @param {Object} [buttons] buttons to show { text: 'Text for the button', onClick: fn() { return true if notification should be dismissed } } + */ + static add(text, buttons = []) { + this.stack.push({ text, buttons }); + } + + /** + * Notifications currently in the stack. + * @type {Object[]} + */ + static get stack() { + return this._stack || (this._stack = []); + } + + /** + * Dismiss a notification at index. + * @param {Number} index Index of the notification + */ + static dismiss(index) { + this.stack.splice(index, 1); + } + +} diff --git a/client/src/ui/ui.js b/client/src/ui/ui.js index 95eb66f4..8b29f2f6 100644 --- a/client/src/ui/ui.js +++ b/client/src/ui/ui.js @@ -3,6 +3,7 @@ export { default as BdUI } from './bdui'; export { default as BdMenu, BdMenuItems } from './bdmenu'; export { default as Modals } from './modals'; export { default as Toasts } from './toasts'; +export { default as Notifications } from './notifications'; export { default as VueInjector } from './vueinjector'; export { default as Reflection } from './reflection'; diff --git a/common/modules/logger.js b/common/modules/logger.js index 9ed5d5a3..8acf3ac6 100644 --- a/common/modules/logger.js +++ b/common/modules/logger.js @@ -37,7 +37,7 @@ export default class Logger { level = Logger.parseLevel(level); message = typeof message === 'object' && message instanceof Array ? message : [message]; - console[level]('[%cBetter%cDiscord:%s]', 'color: #3E82E5', '', `${module}${level === 'debug' ? '|DBG' : ''}`, ...message); + console[level]('[%cBetter%cDiscord:%s]', 'color: #3ecc9c', '', `${module}${level === 'debug' ? '|DBG' : ''}`, ...message); const message_string = message.map(m => typeof m === 'string' ? m : node_utils.inspect(m, {showProxy: true})).join(' '); this.logs.push(`${level.toUpperCase()} : [${Logger.timestamp}|${module}] ${message_string}`); diff --git a/csseditor/src/styles/images.scss b/csseditor/src/styles/images.scss index d488f2ae..202ab708 100644 --- a/csseditor/src/styles/images.scss +++ b/csseditor/src/styles/images.scss @@ -1 +1,2 @@ -$bdicon: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FscXVlXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjAwMCAyMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyMDAwIDIwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGZpbGw9IiMzRTgyRTUiIGQ9Ik0xNDAyLjIsNjMxLjdjLTkuNy0zNTMuNC0yODYuMi00OTYtNjQyLjYtNDk2SDY4LjR2NzE0LjFsNDQyLDM5OFY0OTAuN2gyNTdjMjc0LjUsMCwyNzQuNSwzNDQuOSwwLDM0NC45SDU5Ny42djMyOS41aDE2OS44YzI3NC41LDAsMjc0LjUsMzQ0LjgsMCwzNDQuOGgtNjk5djM1NC45aDY5MS4yYzM1Ni4zLDAsNjMyLjgtMTQyLjYsNjQyLjYtNDk2YzAtMTYyLjYtNDQuNS0yODQuMS0xMjIuOS0zNjguNkMxMzU3LjcsOTE1LjgsMTQwMi4yLDc5NC4zLDE0MDIuMiw2MzEuN3oiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNMTI2Mi41LDEzNS4yTDEyNjIuNSwxMzUuMmwtNzYuOCwwYzI2LjYsMTMuMyw1MS43LDI4LjEsNzUsNDQuM2M3MC43LDQ5LjEsMTI2LjEsMTExLjUsMTY0LjYsMTg1LjNjMzkuOSw3Ni42LDYxLjUsMTY1LjYsNjQuMywyNjQuNmwwLDEuMnYxLjJjMCwxNDEuMSwwLDU5Ni4xLDAsNzM3LjF2MS4ybDAsMS4yYy0yLjcsOTktMjQuMywxODgtNjQuMywyNjQuNmMtMzguNSw3My44LTkzLjgsMTM2LjItMTY0LjYsMTg1LjNjLTIyLjYsMTUuNy00Ni45LDMwLjEtNzIuNiw0My4xaDcyLjVjMzQ2LjIsMS45LDY3MS0xNzEuMiw2NzEtNTY3LjlWNzE2LjdDMTkzMy41LDMxMi4yLDE2MDguNywxMzUuMiwxMjYyLjUsMTM1LjJ6Ii8+PC9nPjwvc3ZnPg==); +$logoSmallGw: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkltYWdlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDUxMiA1MTI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGUgdHlwZT0idGV4dC9jc3MiPi5zdDB7ZGlzcGxheTpub25lO30uc3Qxe2Rpc3BsYXk6aW5saW5lO2ZpbGw6IzAyMDAzNTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LnN0MntmaWxsOiMzRUNDOUU7fS5zdDN7ZmlsbDojRkZGRkZGO308L3N0eWxlPjxnIGlkPSJMYXllcl8yIiBjbGFzcz0ic3QwIj48cmVjdCB4PSItNjQiIHk9Ii0zMiIgY2xhc3M9InN0MSIgd2lkdGg9IjYxOCIgaGVpZ2h0PSI1NzIiLz48L2c+PGcgaWQ9IkxheWVyXzEiIHhtbG5zOnZlY3Rvcm5hdG9yPSJodHRwOi8vdmVjdG9ybmF0b3IuaW8iPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik03MCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3YyMzMuNkM0Mi43LDM5Ny43LDEzNy45LDQ5MywyNTYsNDkzYzI5LjcsMCw1OC02LjEsODMuNi0xN1YzNDEuNWMtMTksMjUuNi00OS4zLDQyLjItODMuNiw0Mi4yYy01Ny42LDAtMTA0LjEtNDYuNS0xMDQuMS0xMDQuMVY0Ni4xYzAtMTMuNy0xMy43LTI3LjMtMjcuMy0yNy4zSDcweiIvPjxwYXRoIGNsYXNzPSJzdDMiIGQ9Ik0zODcuNCwxOC44Yy0xMy43LDAtMjcuMywxMy43LTI3LjMsMjcuM3Y0Ny4zQzMyOS4zLDc2LjIsMjkzLjksNjYuMywyNTYsNjYuM2MtMjkuOCwwLTU3LjksNi4zLTgzLjYsMTcuM3YxMzQuMmMxOS0yNS42LDQ5LjMtNDIuMiw4My42LTQyLjJjNTcuNiwwLDEwNC4xLDQ2LjUsMTA0LjEsMTA0LjF2MTg2LjJjNjUuMi0zNi40LDEwOS4yLTEwNiwxMDkuMi0xODYuMlY0Ni4xYzAtMTguOC0xMy43LTI3LjMtMjcuMy0yNy4zSDM4Ny40eiIvPjwvZz48L3N2Zz4=); +$bdicon: $logoSmallGw;