start to convert emotemenu
This commit is contained in:
parent
e06d2d9d9e
commit
b64f35fa88
|
@ -19,7 +19,7 @@
|
|||
"semi": 2,
|
||||
"space-infix-ops": ["error", {"int32Hint": false}],
|
||||
"quotes": ["error", "double", {"allowTemplateLiterals": true}],
|
||||
"no-console": 0,
|
||||
"no-console": 2,
|
||||
"brace-style": ["error", "stroustrup", {"allowSingleLine": true}],
|
||||
"keyword-spacing": 2,
|
||||
"no-else-return": 2,
|
||||
|
|
16
css/main.css
16
css/main.css
|
@ -308,7 +308,7 @@
|
|||
|
||||
#bda-qem-twitch-container, #bda-qem-favourite-container {
|
||||
width: 346px;
|
||||
height: 327px;
|
||||
height: 329px;
|
||||
background-color: #FFF;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
@ -739,12 +739,12 @@ body .ace_closeButton {
|
|||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
body .ace_closeButton::before {
|
||||
content: "✖";
|
||||
color: #36393f;
|
||||
}
|
||||
|
||||
|
||||
body .ace_closeButton:active {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
@ -1780,11 +1780,11 @@ body .ace_closeButton:active {
|
|||
border-color: #202020;
|
||||
}
|
||||
|
||||
.bda-dark #bda-qem-favourite-container .scroller::-webkit-scrollbar,
|
||||
.bda-dark #bda-qem-favourite-container .scroller::-webkit-scrollbar-track,
|
||||
.bda-dark #bda-qem-favourite-container .scroller::-webkit-scrollbar,
|
||||
.bda-dark #bda-qem-favourite-container .scroller::-webkit-scrollbar-track,
|
||||
.bda-dark #bda-qem-favourite-container .scroller::-webkit-scrollbar-track-piece,
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar,
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar-track,
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar,
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar-track,
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar-track-piece,
|
||||
.bda-dark .emojiPicker-3m1S-j .scroller-3vODG7::-webkit-scrollbar,
|
||||
.bda-dark .emojiPicker-3m1S-j .scroller-3vODG7::-webkit-scrollbar-track,
|
||||
|
@ -1793,7 +1793,7 @@ body .ace_closeButton:active {
|
|||
border-color: #303030 !important;
|
||||
}
|
||||
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar-thumb,
|
||||
.bda-dark #bda-qem-twitch-container .scroller::-webkit-scrollbar-thumb,
|
||||
.bda-dark #bda-qem-favourite-container .scroller::-webkit-scrollbar-thumb,
|
||||
.bda-dark .emojiPicker-3g68GS .scroller-3vODG7::-webkit-scrollbar-thumb {
|
||||
border-color: #202020 !important;
|
||||
|
|
1454
js/main.js
1454
js/main.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -5,4 +5,6 @@ export {default as PublicServers} from "./publicservers";
|
|||
export {default as DarkMode} from "./darkmode";
|
||||
export {default as MinimalMode} from "./minimalmode";
|
||||
export {default as TwentyFourHour} from "./24hour";
|
||||
export {default as ColoredText} from "./coloredtext";
|
||||
export {default as ColoredText} from "./coloredtext";
|
||||
export {default as VoiceDisconnect} from "./voicedisconnect";
|
||||
export {default as EmoteMenu} from "./emotemenu";
|
|
@ -0,0 +1,204 @@
|
|||
import Builtin, {onSettingChange} from "../structs/builtin";
|
||||
import {SettingsCookie, Emotes} from "data";
|
||||
import {DataStore, Utilities, Events} from "modules";
|
||||
|
||||
const headerHTML = `<div id="bda-qem">
|
||||
<button class="active" id="bda-qem-twitch">Twitch</button>
|
||||
<button id="bda-qem-favourite">Favourite</button>
|
||||
<button id="bda-qem-emojis">Emojis</buttond>
|
||||
</div>`;
|
||||
|
||||
const twitchEmoteHTML = `<div id="bda-qem-twitch-container">
|
||||
<div class="scroller-wrap scrollerWrap-2lJEkd fade">
|
||||
<div class="scroller scroller-2FKFPG">
|
||||
<div class="emote-menu-inner">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
const favoritesHTML = `<div id="bda-qem-favourite-container">
|
||||
<div class="scroller-wrap scrollerWrap-2lJEkd fade">
|
||||
<div class="scroller scroller-2FKFPG">
|
||||
<div class="emote-menu-inner">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
const makeEmote = (emote, url, options = {}) => {
|
||||
const {onContextMenu, onClick} = options;
|
||||
const emoteContainer = $(`<div class="emote-container">
|
||||
<img class="emote-icon" alt="${emote}" src="${url}" title="${emote}">
|
||||
</div>`)[0];
|
||||
if (onContextMenu) emoteContainer.addEventListener("contextmenu", onContextMenu);
|
||||
emoteContainer.addEventListener("click", onClick);
|
||||
return emoteContainer;
|
||||
};
|
||||
|
||||
export default new class EmoteMenu extends Builtin {
|
||||
get name() {return "EmoteMenu";}
|
||||
get category() {return "Modules";}
|
||||
get id() {return "bda-es-0";}
|
||||
get hideEmojisID() {return "bda-es-9";}
|
||||
get hideEmojis() {return SettingsCookie[this.hideEmojisID];}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.lastTab = "bda-qem-emojis";
|
||||
this.favoriteEmotes = {};
|
||||
|
||||
this.qmeHeader = $(headerHTML)[0];
|
||||
for (const button of this.qmeHeader.getElementsByTagName("button")) button.addEventListener("click", this.switchMenu.bind(this));
|
||||
|
||||
this.teContainer = $(twitchEmoteHTML)[0];
|
||||
this.teContainerInner = this.teContainer.querySelector(".emote-menu-inner");
|
||||
|
||||
this.faContainer = $(favoritesHTML)[0];
|
||||
this.faContainerInner = this.faContainer.querySelector(".emote-menu-inner");
|
||||
|
||||
this.observer = new MutationObserver(mutations => {for (const mutation of mutations) this.observe(mutation);});
|
||||
this.enableHideEmojis = this.enableHideEmojis.bind(this);
|
||||
this.disableHideEmojis = this.disableHideEmojis.bind(this);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
super.initialize();
|
||||
const fe = DataStore.getBDData("bdfavemotes");
|
||||
if (fe !== "" && fe !== null) this.favoriteEmotes = JSON.parse(atob(fe));
|
||||
this.updateFavorites();
|
||||
}
|
||||
|
||||
async enabled() {
|
||||
await new Promise(resolve => {
|
||||
Events.on("emotes-loaded", resolve);
|
||||
});
|
||||
this.updateTwitchEmotes();
|
||||
this.log("Starting to observe");
|
||||
this.observer.observe(document.getElementById("app-mount"), {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
this.hideEmojiCancel = onSettingChange(this.category, this.hideEmojisID, this.enableHideEmojis, this.disableHideEmojis);
|
||||
if (this.hideEmojis) this.enableHideEmojis();
|
||||
}
|
||||
|
||||
disabled() {
|
||||
this.observer.disconnect();
|
||||
this.disableHideEmojis();
|
||||
if (this.hideEmojiCancel) this.hideEmojiCancel();
|
||||
}
|
||||
|
||||
enableHideEmojis() {
|
||||
$(".emojiPicker-3m1S-j").addClass("bda-qme-hidden");
|
||||
}
|
||||
|
||||
disableHideEmojis() {
|
||||
$(".emojiPicker-3m1S-j").removeClass("bda-qme-hidden");
|
||||
}
|
||||
|
||||
insertEmote(emote) {
|
||||
const ta = Utilities.getTextArea();
|
||||
Utilities.insertText(ta[0], ta.val().slice(-1) == " " ? ta.val() + emote : ta.val() + " " + emote);
|
||||
}
|
||||
|
||||
favContext(e) {
|
||||
e.stopPropagation();
|
||||
const em = e.target.closest(".emote-container").children[0];
|
||||
const menu = $(`<div id="removemenu" class="bd-context-menu context-menu theme-dark">Remove</div>`);
|
||||
menu.css({
|
||||
top: e.pageY - $("#bda-qem-favourite-container").offset().top,
|
||||
left: e.pageX - $("#bda-qem-favourite-container").offset().left
|
||||
});
|
||||
$(em).parent().append(menu);
|
||||
menu.on("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$(em).remove();
|
||||
delete this.favoriteEmotes[$(em).attr("title")];
|
||||
this.updateFavorites();
|
||||
$(document).off("mousedown.emotemenu");
|
||||
});
|
||||
$(document).on("mousedown.emotemenu", function(e) {
|
||||
if (e.target.id == "removemenu") return;
|
||||
$("#removemenu").remove();
|
||||
$(document).off("mousedown.emotemenu");
|
||||
});
|
||||
}
|
||||
|
||||
switchMenu(e) {
|
||||
let id = typeof(e) == "string" ? e : $(e.target).attr("id");
|
||||
if (id == "bda-qem-emojis" && this.hideEmojis) id = "bda-qem-favourite";
|
||||
const twitch = $("#bda-qem-twitch");
|
||||
const fav = $("#bda-qem-favourite");
|
||||
const emojis = $("#bda-qem-emojis");
|
||||
twitch.removeClass("active");
|
||||
fav.removeClass("active");
|
||||
emojis.removeClass("active");
|
||||
|
||||
$(".emojiPicker-3m1S-j").hide();
|
||||
$("#bda-qem-favourite-container").hide();
|
||||
$("#bda-qem-twitch-container").hide();
|
||||
|
||||
switch (id) {
|
||||
case "bda-qem-twitch":
|
||||
twitch.addClass("active");
|
||||
$("#bda-qem-twitch-container").show();
|
||||
break;
|
||||
case "bda-qem-favourite":
|
||||
fav.addClass("active");
|
||||
$("#bda-qem-favourite-container").show();
|
||||
break;
|
||||
case "bda-qem-emojis":
|
||||
emojis.addClass("active");
|
||||
$(".emojiPicker-3m1S-j").show();
|
||||
$(".emojiPicker-3m1S-j input").focus();
|
||||
break;
|
||||
}
|
||||
if (id) this.lastTab = id;
|
||||
}
|
||||
|
||||
observe(mutation) {
|
||||
if (!mutation.addedNodes.length || !(mutation.addedNodes[0] instanceof Element)) return;
|
||||
const node = mutation.addedNodes[0];
|
||||
if (!node.classList.contains("popout-3sVMXz") || node.classList.contains("popoutLeft-30WmrD") || !node.getElementsByClassName("emojiPicker-3m1S-j").length) return;
|
||||
|
||||
const e = $(node);
|
||||
if (this.hideEmojis) e.addClass("bda-qme-hidden");
|
||||
else e.removeClass("bda-qme-hidden");
|
||||
|
||||
e.prepend(this.qmeHeader);
|
||||
e.append(this.teContainer);
|
||||
e.append(this.faContainer);
|
||||
|
||||
this.switchMenu(this.lastTab);
|
||||
}
|
||||
|
||||
favorite(name, url) {
|
||||
if (!this.favoriteEmotes.hasOwnProperty(name)) this.favoriteEmotes[name] = url;
|
||||
this.updateFavorites();
|
||||
}
|
||||
|
||||
updateTwitchEmotes() {
|
||||
while (this.teContainerInner.firstChild) this.teContainerInner.firstChild.remove();
|
||||
for (const emote in Emotes.TwitchGlobal) {
|
||||
if (!Emotes.TwitchGlobal.hasOwnProperty(emote)) continue;
|
||||
const url = Emotes.TwitchGlobal[emote];
|
||||
const emoteElement = makeEmote(emote, url, {onClick: this.insertEmote.bind(this, emote)});
|
||||
this.teContainerInner.append(emoteElement);
|
||||
}
|
||||
}
|
||||
|
||||
updateFavorites() {
|
||||
while (this.faContainerInner.firstChild) this.faContainerInner.firstChild.remove();
|
||||
for (const emote in this.favoriteEmotes) {
|
||||
const url = this.favoriteEmotes[emote];
|
||||
const emoteElement = makeEmote(emote, url, {onClick: this.insertEmote.bind(this, emote), onContextMenu: this.favContext.bind(this)});
|
||||
this.faContainerInner.append(emoteElement);
|
||||
}
|
||||
DataStore.setBDData("bdfavemotes", btoa(JSON.stringify(this.favoriteEmotes)));
|
||||
}
|
||||
|
||||
};
|
|
@ -43,7 +43,6 @@ export default new class PublicServers extends Builtin {
|
|||
}
|
||||
|
||||
render() {
|
||||
// BdApi.alert("Broken", "Sorry but the Public Servers modules is currently broken, I recommend disabling this feature for now.");
|
||||
const root = this.root;
|
||||
if (!root) {
|
||||
console.log("FAILED TO LOCATE ROOT: .layers");
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import Builtin from "../structs/builtin";
|
||||
import {DiscordModules} from "modules";
|
||||
|
||||
export default new class DarkMode extends Builtin {
|
||||
get name() {return "VoiceDisconnect";}
|
||||
get category() {return "Modules";}
|
||||
get id() {return "bda-dc-0";}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.beforeUnload = this.beforeUnload.bind(this);
|
||||
}
|
||||
|
||||
enabled() {
|
||||
window.addEventListener("beforeunload", this.beforeUnload);
|
||||
}
|
||||
|
||||
disabled() {
|
||||
window.removeEventListener("beforeunload", this.beforeUnload);
|
||||
}
|
||||
|
||||
beforeUnload() {
|
||||
DiscordModules.ChannelActions.selectVoiceChannel(null, null);
|
||||
}
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
import {SettingsCookie, SettingsInfo, PluginCookie, ThemeCookie, Plugins, Themes, Emotes, EmoteBlacklist} from "data";
|
||||
import {SettingsCookie, SettingsInfo, Config, PluginCookie, ThemeCookie, Plugins, Themes, Emotes, EmoteBlacklist} from "data";
|
||||
import proxyLocalStorage from "./localstorage";
|
||||
import Core from "./modules/core";
|
||||
import BdApi from "./modules/pluginapi";
|
||||
|
@ -27,7 +27,10 @@ window.bdplugins = Plugins;
|
|||
window.bdEmotes = Emotes;
|
||||
window.bemotes = EmoteBlacklist;
|
||||
window.bdPluginStorage = bdPluginStorage;
|
||||
|
||||
|
||||
window.BDEvents = Events;
|
||||
window.bdConfig = Config;
|
||||
|
||||
export default class CoreWrapper {
|
||||
constructor(config) {
|
||||
|
|
|
@ -85,4 +85,12 @@ export default new class {
|
|||
}});
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// lc = WebpackModules.getByDisplayName("FluxContainer(Layers)")
|
||||
// Patcher.after(lc.prototype, "render", (t,a,r) => {console.log(t,a,r);})
|
||||
// return.type
|
||||
// Patcher.after(temp3.prototype, "renderLayers", (t,a,r) => {
|
||||
// console.log(t,a,r);
|
||||
// if (t.props.layers.includes("USER_SETTINGS")) r[1].props.className = "user-settings-prop";
|
||||
// })
|
|
@ -2,15 +2,13 @@ import BDV2 from "./bdv2";
|
|||
import Utilities from "./utilities";
|
||||
import {Config, SettingsCookie} from "data";
|
||||
import EmoteModule from "./emotes";
|
||||
import QuickEmoteMenu from "./emotemenu";
|
||||
// import VoiceMode from "./voicemode";
|
||||
// import DevMode from "./devmode";
|
||||
// import QuickEmoteMenu from "../builtins/emotemenu";
|
||||
import PluginManager from "./pluginmanager";
|
||||
import ThemeManager from "./thememanager";
|
||||
import DataStore from "./datastore";
|
||||
// import PublicServers from "./publicservers";
|
||||
import SettingsPanel from "./settingspanel";
|
||||
import * as Builtins from "builtins";
|
||||
import {Modals} from "ui";
|
||||
import Events from "./emitter";
|
||||
|
||||
function Core() {
|
||||
}
|
||||
|
@ -21,25 +19,26 @@ Core.prototype.setConfig = function(config) {
|
|||
|
||||
Core.prototype.init = async function() {
|
||||
if (Config.version < Config.minSupportedVersion) {
|
||||
this.alert("Not Supported", "BetterDiscord v" + Config.version + " (your version)" + " is not supported by the latest js (" + Config.bbdVersion + ").<br><br> Please download the latest version from <a href='https://github.com/rauenzi/BetterDiscordApp/releases/latest' target='_blank'>GitHub</a>");
|
||||
Modals.alert("Not Supported", "BetterDiscord v" + Config.version + " (your version)" + " is not supported by the latest js (" + Config.bbdVersion + ").<br><br> Please download the latest version from <a href='https://github.com/rauenzi/BetterDiscordApp/releases/latest' target='_blank'>GitHub</a>");
|
||||
return;
|
||||
}
|
||||
|
||||
const latestLocalVersion = Config.updater ? Config.updater.LatestVersion : Config.latestVersion;
|
||||
if (latestLocalVersion > Config.version) {
|
||||
this.alert("Update Available", `
|
||||
Modals.alert("Update Available", `
|
||||
An update for BandagedBD is available (${latestLocalVersion})! Please Reinstall!<br /><br />
|
||||
<a href='https://github.com/rauenzi/BetterDiscordApp/releases/latest' target='_blank'>Download Installer</a>
|
||||
`);
|
||||
}
|
||||
|
||||
Utilities.log("Startup", "Initializing Settings");
|
||||
this.initSettings();
|
||||
SettingsPanel.initialize();
|
||||
Utilities.log("Startup", "Initializing EmoteModule");
|
||||
window.emotePromise = EmoteModule.init().then(() => {
|
||||
EmoteModule.initialized = true;
|
||||
Utilities.log("Startup", "Initializing QuickEmoteMenu");
|
||||
QuickEmoteMenu.init();
|
||||
Events.dispatch("emotes-loaded");
|
||||
// QuickEmoteMenu.init();
|
||||
});
|
||||
|
||||
this.injectExternals();
|
||||
|
@ -58,10 +57,6 @@ Core.prototype.init = async function() {
|
|||
|
||||
$("#customcss").detach().appendTo(document.head);
|
||||
|
||||
window.addEventListener("beforeunload", function() {
|
||||
if (SettingsCookie["bda-dc-0"]) document.querySelector(".btn.btn-disconnect").click();
|
||||
});
|
||||
|
||||
// PublicServers.initialize();
|
||||
EmoteModule.autoCapitalize();
|
||||
|
||||
|
@ -73,13 +68,8 @@ Core.prototype.init = async function() {
|
|||
// Show loading errors
|
||||
if (SettingsCookie["fork-ps-1"]) {
|
||||
Utilities.log("Startup", "Collecting Startup Errors");
|
||||
this.showContentErrors({plugins: pluginErrors, themes: themeErrors});
|
||||
Modals.showContentErrors({plugins: pluginErrors, themes: themeErrors});
|
||||
}
|
||||
|
||||
// if (!DataStore.getBDData(bbdVersion)) {
|
||||
// BdApi.alert("BBD Updated!", ["Lots of things were fixed in this update like Public Servers, Minimal Mode, Dark Mode and 24 Hour Timestamps.", BdApi.React.createElement("br"), BdApi.React.createElement("br"), "Feel free to test them all out!"]);
|
||||
// DataStore.setBDData(bbdVersion, true);
|
||||
// }
|
||||
};
|
||||
|
||||
Core.prototype.checkForGuilds = function() {
|
||||
|
@ -102,26 +92,6 @@ Core.prototype.injectExternals = async function() {
|
|||
if (window.require.original) window.require = window.require.original;
|
||||
};
|
||||
|
||||
Core.prototype.initSettings = function () {
|
||||
DataStore.initialize();
|
||||
if (!DataStore.getSettingGroup("settings")) return this.saveSettings();
|
||||
const savedSettings = this.loadSettings();
|
||||
$("<style id=\"customcss\">").text(atob(DataStore.getBDData("bdcustomcss"))).appendTo(document.head);
|
||||
for (const setting in savedSettings) {
|
||||
if (savedSettings[setting] !== undefined) SettingsCookie[setting] = savedSettings[setting];
|
||||
}
|
||||
this.saveSettings();
|
||||
|
||||
};
|
||||
|
||||
Core.prototype.saveSettings = function () {
|
||||
DataStore.setSettingGroup("settings", SettingsCookie);
|
||||
};
|
||||
|
||||
Core.prototype.loadSettings = function () {
|
||||
return DataStore.getSettingGroup("settings");
|
||||
};
|
||||
|
||||
Core.prototype.initObserver = function () {
|
||||
const mainObserver = new MutationObserver((mutations) => {
|
||||
|
||||
|
@ -143,10 +113,6 @@ Core.prototype.initObserver = function () {
|
|||
if (!document.getElementById("bd-settings-sidebar")) SettingsPanel.renderSidebar();
|
||||
}
|
||||
}
|
||||
|
||||
// Emoji Picker
|
||||
if (node.classList.contains("popout-3sVMXz") && !node.classList.contains("popoutLeft-30WmrD") && node.getElementsByClassName("emojiPicker-3m1S-j").length) QuickEmoteMenu.obsCallback(node);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -156,147 +122,5 @@ Core.prototype.initObserver = function () {
|
|||
});
|
||||
};
|
||||
|
||||
Core.prototype.alert = function(title, content) {
|
||||
const modal = $(`<div class="bd-modal-wrapper theme-dark">
|
||||
<div class="bd-backdrop backdrop-1wrmKB"></div>
|
||||
<div class="bd-modal modal-1UGdnR">
|
||||
<div class="bd-modal-inner inner-1JeGVc">
|
||||
<div class="header header-1R_AjF">
|
||||
<div class="title">${title}</div>
|
||||
</div>
|
||||
<div class="bd-modal-body">
|
||||
<div class="scroller-wrap fade">
|
||||
<div class="scroller">
|
||||
${content}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer footer-2yfCgX">
|
||||
<button type="button">Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
modal.find(".footer button").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.find(".bd-backdrop").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.appendTo("#app-mount");
|
||||
};
|
||||
|
||||
Core.prototype.showContentErrors = function({plugins: pluginErrors = [], themes: themeErrors = []}) {
|
||||
if (!pluginErrors || !themeErrors) return;
|
||||
if (!pluginErrors.length && !themeErrors.length) return;
|
||||
const modal = $(`<div class="bd-modal-wrapper theme-dark">
|
||||
<div class="bd-backdrop backdrop-1wrmKB"></div>
|
||||
<div class="bd-modal bd-content-modal modal-1UGdnR">
|
||||
<div class="bd-modal-inner inner-1JeGVc">
|
||||
<div class="header header-1R_AjF"><div class="title">Content Errors</div></div>
|
||||
<div class="bd-modal-body">
|
||||
<div class="tab-bar-container">
|
||||
<div class="tab-bar TOP">
|
||||
<div class="tab-bar-item">Plugins</div>
|
||||
<div class="tab-bar-item">Themes</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-header">
|
||||
<div class="table-column column-name">Name</div>
|
||||
<div class="table-column column-message">Message</div>
|
||||
<div class="table-column column-error">Error</div>
|
||||
</div>
|
||||
<div class="scroller-wrap fade">
|
||||
<div class="scroller">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer footer-2yfCgX">
|
||||
<button type="button">Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
|
||||
function generateTab(errors) {
|
||||
const container = $(`<div class="errors">`);
|
||||
for (const err of errors) {
|
||||
const error = $(`<div class="error">
|
||||
<div class="table-column column-name">${err.name ? err.name : err.file}</div>
|
||||
<div class="table-column column-message">${err.message}</div>
|
||||
<div class="table-column column-error"><a class="error-link" href="">${err.error ? err.error.message : ""}</a></div>
|
||||
</div>`);
|
||||
container.append(error);
|
||||
if (err.error) {
|
||||
error.find("a").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
Utilities.err("ContentManager", `Error details for ${err.name ? err.name : err.file}.`, err.error);
|
||||
});
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
const tabs = [generateTab(pluginErrors), generateTab(themeErrors)];
|
||||
|
||||
modal.find(".tab-bar-item").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
modal.find(".tab-bar-item").removeClass("selected");
|
||||
$(e.target).addClass("selected");
|
||||
modal.find(".scroller").empty().append(tabs[$(e.target).index()]);
|
||||
});
|
||||
|
||||
modal.find(".footer button").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.find(".bd-backdrop").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.appendTo("#app-mount");
|
||||
if (pluginErrors.length) modal.find(".tab-bar-item")[0].click();
|
||||
else modal.find(".tab-bar-item")[1].click();
|
||||
};
|
||||
|
||||
/**
|
||||
* This shows a toast similar to android towards the bottom of the screen.
|
||||
*
|
||||
* @param {string} content The string to show in the toast.
|
||||
* @param {object} options Options object. Optional parameter.
|
||||
* @param {string} options.type Changes the type of the toast stylistically and semantically. Choices: "", "info", "success", "danger"/"error", "warning"/"warn". Default: ""
|
||||
* @param {boolean} options.icon Determines whether the icon should show corresponding to the type. A toast without type will always have no icon. Default: true
|
||||
* @param {number} options.timeout Adjusts the time (in ms) the toast should be shown for before disappearing automatically. Default: 3000
|
||||
*/
|
||||
Core.prototype.showToast = function(content, options = {}) {
|
||||
if (!Config.deferLoaded) return;
|
||||
if (!document.querySelector(".bd-toasts")) {
|
||||
const toastWrapper = document.createElement("div");
|
||||
toastWrapper.classList.add("bd-toasts");
|
||||
const boundingElement = document.querySelector(".chat-3bRxxu form, #friends, .noChannel-Z1DQK7, .activityFeed-28jde9");
|
||||
toastWrapper.style.setProperty("left", boundingElement ? boundingElement.getBoundingClientRect().left + "px" : "0px");
|
||||
toastWrapper.style.setProperty("width", boundingElement ? boundingElement.offsetWidth + "px" : "100%");
|
||||
toastWrapper.style.setProperty("bottom", (document.querySelector(".chat-3bRxxu form") ? document.querySelector(".chat-3bRxxu form").offsetHeight : 80) + "px");
|
||||
document.querySelector(".app, .app-2rEoOp").appendChild(toastWrapper);
|
||||
}
|
||||
const {type = "", icon = true, timeout = 3000} = options;
|
||||
const toastElem = document.createElement("div");
|
||||
toastElem.classList.add("bd-toast");
|
||||
if (type) toastElem.classList.add("toast-" + type);
|
||||
if (type && icon) toastElem.classList.add("icon");
|
||||
toastElem.innerText = content;
|
||||
document.querySelector(".bd-toasts").appendChild(toastElem);
|
||||
setTimeout(() => {
|
||||
toastElem.classList.add("closing");
|
||||
setTimeout(() => {
|
||||
toastElem.remove();
|
||||
if (!document.querySelectorAll(".bd-toasts .bd-toast").length) document.querySelector(".bd-toasts").remove();
|
||||
}, 300);
|
||||
}, timeout);
|
||||
};
|
||||
|
||||
|
||||
export default new Core();
|
|
@ -1,5 +1,5 @@
|
|||
import {Config} from "data";
|
||||
import BdApi from "./pluginapi";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const releaseChannel = DiscordNative.globals.releaseChannel;
|
||||
|
@ -11,20 +11,15 @@ export default new class DataStore {
|
|||
}
|
||||
|
||||
initialize() {
|
||||
try {
|
||||
if (!fs.existsSync(this.BDFile)) fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4));
|
||||
const data = __non_webpack_require__(this.BDFile);
|
||||
if (data.hasOwnProperty("settings")) this.data = data;
|
||||
if (!fs.existsSync(this.settingsFile)) return;
|
||||
let settings = __non_webpack_require__(this.settingsFile);
|
||||
fs.unlinkSync(this.settingsFile);
|
||||
if (settings.hasOwnProperty("settings")) settings = Object.assign({stable: {}, canary: {}, ptb: {}}, {[releaseChannel]: settings});
|
||||
else settings = Object.assign({stable: {}, canary: {}, ptb: {}}, settings);
|
||||
this.setBDData("settings", settings);
|
||||
}
|
||||
catch (err) {
|
||||
BdApi.alert("Corrupt Storage", "The bd storage has somehow become corrupt. You may either try to salvage the file or delete it then reload.");
|
||||
}
|
||||
if (!fs.existsSync(this.BDFile)) fs.writeFileSync(this.BDFile, JSON.stringify(this.data, null, 4));
|
||||
const data = __non_webpack_require__(this.BDFile);
|
||||
if (data.hasOwnProperty("settings")) this.data = data;
|
||||
if (!fs.existsSync(this.settingsFile)) return;
|
||||
let settings = __non_webpack_require__(this.settingsFile);
|
||||
fs.unlinkSync(this.settingsFile);
|
||||
if (settings.hasOwnProperty("settings")) settings = Object.assign({stable: {}, canary: {}, ptb: {}}, {[releaseChannel]: settings});
|
||||
else settings = Object.assign({stable: {}, canary: {}, ptb: {}}, settings);
|
||||
this.setBDData("settings", settings);
|
||||
}
|
||||
|
||||
get BDFile() {return this._BDFile || (this._BDFile = path.resolve(Config.dataPath, "bdstorage.json"));}
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
/**
|
||||
* A large list of known and useful webpack modules internal to Discord.
|
||||
* Click the source link down below to view more info. Otherwise, if you
|
||||
* have the library installed or have a plugin using this library,
|
||||
* do `Object.keys(ZLibrary.DiscordModules)` in console for a list of modules.
|
||||
* @module DiscordModules
|
||||
* @version 0.0.3
|
||||
*/
|
||||
import Utilities from "./utilities";
|
||||
import WebpackModules from "./webpackmodules";
|
||||
|
||||
export default Utilities.memoizeObject({
|
||||
get React() {return WebpackModules.getByProps("createElement", "cloneElement");},
|
||||
get ReactDOM() {return WebpackModules.getByProps("render", "findDOMNode");},
|
||||
get Flux() {return WebpackModules.getByProps("connectStores");},
|
||||
get Events() {return WebpackModules.getByPrototypes("setMaxListeners", "emit");},
|
||||
|
||||
/* Guild Info, Stores, and Utilities */
|
||||
get GuildStore() {return WebpackModules.getByProps("getGuild");},
|
||||
get SortedGuildStore() {return WebpackModules.getByProps("getSortedGuilds");},
|
||||
get SelectedGuildStore() {return WebpackModules.getByProps("getLastSelectedGuildId");},
|
||||
get GuildSync() {return WebpackModules.getByProps("getSyncedGuilds");},
|
||||
get GuildInfo() {return WebpackModules.getByProps("getAcronym");},
|
||||
get GuildChannelsStore() {return WebpackModules.getByProps("getChannels", "getDefaultChannel");},
|
||||
get GuildMemberStore() {return WebpackModules.getByProps("getMember");},
|
||||
get MemberCountStore() {return WebpackModules.getByProps("getMemberCounts");},
|
||||
get GuildEmojiStore() {return WebpackModules.getByProps("getEmojis");},
|
||||
get GuildActions() {return WebpackModules.getByProps("markGuildAsRead");},
|
||||
get GuildPermissions() {return WebpackModules.getByProps("getGuildPermissions");},
|
||||
|
||||
/* Channel Store & Actions */
|
||||
get ChannelStore() {return WebpackModules.getByProps("getChannels", "getDMFromUserId");},
|
||||
get SelectedChannelStore() {return WebpackModules.getByProps("getLastSelectedChannelId");},
|
||||
get ChannelActions() {return WebpackModules.getByProps("selectChannel");},
|
||||
get PrivateChannelActions() {return WebpackModules.getByProps("openPrivateChannel");},
|
||||
get ChannelSelector() {return WebpackModules.getByProps("selectGuild", "selectChannel");},
|
||||
|
||||
/* Current User Info, State and Settings */
|
||||
get UserInfoStore() {return WebpackModules.getByProps("getToken");},
|
||||
get UserSettingsStore() {return WebpackModules.getByProps("guildPositions");},
|
||||
get AccountManager() {return WebpackModules.getByProps("register", "login");},
|
||||
get UserSettingsUpdater() {return WebpackModules.getByProps("updateRemoteSettings");},
|
||||
get OnlineWatcher() {return WebpackModules.getByProps("isOnline");},
|
||||
get CurrentUserIdle() {return WebpackModules.getByProps("getIdleTime");},
|
||||
get RelationshipStore() {return WebpackModules.getByProps("isBlocked", "getFriendIDs");},
|
||||
get RelationshipManager() {return WebpackModules.getByProps("addRelationship");},
|
||||
get MentionStore() {return WebpackModules.getByProps("getMentions");},
|
||||
|
||||
/* User Stores and Utils */
|
||||
get UserStore() {return WebpackModules.getByProps("getCurrentUser");},
|
||||
get UserStatusStore() {return WebpackModules.getByProps("getStatus", "getState");},
|
||||
get UserTypingStore() {return WebpackModules.getByProps("isTyping");},
|
||||
get UserActivityStore() {return WebpackModules.getByProps("getActivity");},
|
||||
get UserNameResolver() {return WebpackModules.getByProps("getName");},
|
||||
get UserNoteStore() {return WebpackModules.getByProps("getNote");},
|
||||
get UserNoteActions() {return WebpackModules.getByProps("updateNote");},
|
||||
|
||||
/* Emoji Store and Utils */
|
||||
get EmojiInfo() {return WebpackModules.getByProps("isEmojiDisabled");},
|
||||
get EmojiUtils() {return WebpackModules.getByProps("getGuildEmoji");},
|
||||
get EmojiStore() {return WebpackModules.getByProps("getByCategory", "EMOJI_NAME_RE");},
|
||||
|
||||
/* Invite Store and Utils */
|
||||
get InviteStore() {return WebpackModules.getByProps("getInvites");},
|
||||
get InviteResolver() {return WebpackModules.getByProps("findInvite");},
|
||||
get InviteActions() {return WebpackModules.getByProps("acceptInvite");},
|
||||
|
||||
/* Discord Objects & Utils */
|
||||
get DiscordConstants() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes");},
|
||||
get DiscordPermissions() {return WebpackModules.getByProps("Permissions", "ActivityTypes", "StatusTypes").Permissions;},
|
||||
get PermissionUtils() {return WebpackModules.getByProps("getHighestRole");},
|
||||
get ColorConverter() {return WebpackModules.getByProps("hex2int");},
|
||||
get ColorShader() {return WebpackModules.getByProps("darken");},
|
||||
get TinyColor() {return WebpackModules.getByPrototypes("toRgb");},
|
||||
get ClassResolver() {return WebpackModules.getByProps("getClass");},
|
||||
get ButtonData() {return WebpackModules.getByProps("ButtonSizes");},
|
||||
get IconNames() {return WebpackModules.getByProps("IconNames");},
|
||||
get NavigationUtils() {return WebpackModules.getByProps("transitionTo", "replaceWith", "getHistory");},
|
||||
|
||||
/* Discord Messages */
|
||||
get MessageStore() {return WebpackModules.getByProps("getMessages");},
|
||||
get MessageActions() {return WebpackModules.getByProps("jumpToMessage", "_sendMessage");},
|
||||
get MessageQueue() {return WebpackModules.getByProps("enqueue");},
|
||||
get MessageParser() {return WebpackModules.getByProps("createMessage", "parse", "unparse");},
|
||||
|
||||
/* Text Processing */
|
||||
get hljs() {return WebpackModules.getByProps("highlight", "highlightBlock");},
|
||||
get SimpleMarkdown() {return WebpackModules.getByProps("parseBlock", "parseInline", "defaultOutput");},
|
||||
|
||||
/* Experiments */
|
||||
get ExperimentStore() {return WebpackModules.getByProps("getExperimentOverrides");},
|
||||
get ExperimentsManager() {return WebpackModules.getByProps("isDeveloper");},
|
||||
get CurrentExperiment() {return WebpackModules.getByProps("getExperimentId");},
|
||||
|
||||
/* Images, Avatars and Utils */
|
||||
get ImageResolver() {return WebpackModules.getByProps("getUserAvatarURL", "getGuildIconURL");},
|
||||
get ImageUtils() {return WebpackModules.getByProps("getSizedImageSrc");},
|
||||
get AvatarDefaults() {return WebpackModules.getByProps("getUserAvatarURL", "DEFAULT_AVATARS");},
|
||||
|
||||
/* Window, DOM, HTML */
|
||||
get WindowInfo() {return WebpackModules.getByProps("isFocused", "windowSize");},
|
||||
get TagInfo() {return WebpackModules.getByProps("VALID_TAG_NAMES");},
|
||||
get DOMInfo() {return WebpackModules.getByProps("canUseDOM");},
|
||||
|
||||
/* Locale/Location and Time */
|
||||
get LocaleManager() {return WebpackModules.getByProps("setLocale");},
|
||||
get Moment() {return WebpackModules.getByProps("parseZone");},
|
||||
get LocationManager() {return WebpackModules.getByProps("createLocation");},
|
||||
get Timestamps() {return WebpackModules.getByProps("fromTimestamp");},
|
||||
|
||||
/* Strings and Utils */
|
||||
get Strings() {return WebpackModules.getByProps("Messages").Messages;},
|
||||
get StringFormats() {return WebpackModules.getByProps("a", "z");},
|
||||
get StringUtils() {return WebpackModules.getByProps("toASCII");},
|
||||
|
||||
/* URLs and Utils */
|
||||
get URLParser() {return WebpackModules.getByProps("Url", "parse");},
|
||||
get ExtraURLs() {return WebpackModules.getByProps("getArticleURL");},
|
||||
|
||||
/* Drag & Drop */
|
||||
get DNDActions() {return WebpackModules.getByProps("beginDrag");},
|
||||
get DNDSources() {return WebpackModules.getByProps("addTarget");},
|
||||
get DNDObjects() {return WebpackModules.getByProps("DragSource");},
|
||||
|
||||
/* Media Stuff (Audio/Video) */
|
||||
get MediaDeviceInfo() {return WebpackModules.getByProps("Codecs", "SUPPORTED_BROWSERS");},
|
||||
get MediaInfo() {return WebpackModules.getByProps("getOutputVolume");},
|
||||
get MediaEngineInfo() {return WebpackModules.getByProps("MediaEngineFeatures");},
|
||||
get VoiceInfo() {return WebpackModules.getByProps("EchoCancellation");},
|
||||
get VideoStream() {return WebpackModules.getByProps("getVideoStream");},
|
||||
get SoundModule() {return WebpackModules.getByProps("playSound");},
|
||||
|
||||
/* Electron & Other Internals with Utils*/
|
||||
get ElectronModule() {return WebpackModules.getByProps("setBadge");},
|
||||
get Dispatcher() {return WebpackModules.getByProps("dirtyDispatch");},
|
||||
get PathUtils() {return WebpackModules.getByProps("hasBasename");},
|
||||
get NotificationModule() {return WebpackModules.getByProps("showNotification");},
|
||||
get RouterModule() {return WebpackModules.getByProps("Router");},
|
||||
get APIModule() {return WebpackModules.getByProps("getAPIBaseURL");},
|
||||
get AnalyticEvents() {return WebpackModules.getByProps("AnalyticEventConfigs");},
|
||||
get KeyGenerator() {return WebpackModules.getByRegex(/"binary"/);},
|
||||
get Buffers() {return WebpackModules.getByProps("Buffer", "kMaxLength");},
|
||||
get DeviceStore() {return WebpackModules.getByProps("getDevices");},
|
||||
get SoftwareInfo() {return WebpackModules.getByProps("os");},
|
||||
get CurrentContext() {return WebpackModules.getByProps("setTagsContext");}
|
||||
});
|
|
@ -1,5 +1,9 @@
|
|||
const EventEmitter = require("events");
|
||||
export default new class BDEvents extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.setMaxListeners(20);
|
||||
}
|
||||
dispatch(eventName, ...args) {
|
||||
this.emit(eventName, ...args);
|
||||
}
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
import {SettingsCookie, Emotes} from "data";
|
||||
import DataStore from "./datastore";
|
||||
import Utilities from "./utilities";
|
||||
|
||||
function QuickEmoteMenu() {
|
||||
|
||||
}
|
||||
|
||||
QuickEmoteMenu.prototype.init = function() {
|
||||
this.initialized = true;
|
||||
$(document).on("mousedown", function(e) {
|
||||
if (e.target.id != "rmenu") $("#rmenu").remove();
|
||||
});
|
||||
this.favoriteEmotes = {};
|
||||
const fe = DataStore.getBDData("bdfavemotes");
|
||||
if (fe !== "" && fe !== null) {
|
||||
this.favoriteEmotes = JSON.parse(atob(fe));
|
||||
}
|
||||
|
||||
let qmeHeader = "";
|
||||
qmeHeader += "<div id=\"bda-qem\">";
|
||||
qmeHeader += " <button class=\"active\" id=\"bda-qem-twitch\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Twitch</button>";
|
||||
qmeHeader += " <button id=\"bda-qem-favourite\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Favourite</button>";
|
||||
qmeHeader += " <button id=\"bda-qem-emojis\" onclick='quickEmoteMenu.switchHandler(this); return false;'>Emojis</buttond>";
|
||||
qmeHeader += "</div>";
|
||||
this.qmeHeader = qmeHeader;
|
||||
|
||||
let teContainer = "";
|
||||
teContainer += "<div id=\"bda-qem-twitch-container\">";
|
||||
teContainer += " <div class=\"scroller-wrap scrollerWrap-2lJEkd fade\">";
|
||||
teContainer += " <div class=\"scroller scroller-2FKFPG\">";
|
||||
teContainer += " <div class=\"emote-menu-inner\">";
|
||||
let url = "";
|
||||
for (const emote in Emotes.TwitchGlobal) {
|
||||
if (Emotes.TwitchGlobal.hasOwnProperty(emote)) {
|
||||
url = Emotes.TwitchGlobal[emote];
|
||||
teContainer += "<div class=\"emote-container\">";
|
||||
teContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\">";
|
||||
teContainer += " </img>";
|
||||
teContainer += "</div>";
|
||||
}
|
||||
}
|
||||
teContainer += " </div>";
|
||||
teContainer += " </div>";
|
||||
teContainer += " </div>";
|
||||
teContainer += "</div>";
|
||||
this.teContainer = teContainer;
|
||||
|
||||
let faContainer = "";
|
||||
faContainer += "<div id=\"bda-qem-favourite-container\">";
|
||||
faContainer += " <div class=\"scroller-wrap scrollerWrap-2lJEkd fade\">";
|
||||
faContainer += " <div class=\"scroller scroller-2FKFPG\">";
|
||||
faContainer += " <div class=\"emote-menu-inner\">";
|
||||
for (const emote in this.favoriteEmotes) {
|
||||
url = this.favoriteEmotes[emote];
|
||||
faContainer += "<div class=\"emote-container\">";
|
||||
faContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\" oncontextmenu='quickEmoteMenu.favContext(event, this);'>";
|
||||
faContainer += " </img>";
|
||||
faContainer += "</div>";
|
||||
}
|
||||
faContainer += " </div>";
|
||||
faContainer += " </div>";
|
||||
faContainer += " </div>";
|
||||
faContainer += "</div>";
|
||||
this.faContainer = faContainer;
|
||||
};
|
||||
|
||||
QuickEmoteMenu.prototype.favContext = function(e, em) {
|
||||
e.stopPropagation();
|
||||
const menu = $("<div>", {"id": "removemenu", "data-emoteid": $(em).prop("title"), "text": "Remove", "class": "bd-context-menu context-menu theme-dark"});
|
||||
menu.css({
|
||||
top: e.pageY - $("#bda-qem-favourite-container").offset().top,
|
||||
left: e.pageX - $("#bda-qem-favourite-container").offset().left
|
||||
});
|
||||
$(em).parent().append(menu);
|
||||
menu.on("click", function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$(this).remove();
|
||||
|
||||
delete this.favoriteEmotes[$(this).data("emoteid")];
|
||||
this.updateFavorites();
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
QuickEmoteMenu.prototype.switchHandler = function(e) {
|
||||
this.switchQem($(e).attr("id"));
|
||||
};
|
||||
|
||||
QuickEmoteMenu.prototype.switchQem = function(id) {
|
||||
const twitch = $("#bda-qem-twitch");
|
||||
const fav = $("#bda-qem-favourite");
|
||||
const emojis = $("#bda-qem-emojis");
|
||||
twitch.removeClass("active");
|
||||
fav.removeClass("active");
|
||||
emojis.removeClass("active");
|
||||
|
||||
$(".emojiPicker-3m1S-j").hide();
|
||||
$("#bda-qem-favourite-container").hide();
|
||||
$("#bda-qem-twitch-container").hide();
|
||||
|
||||
switch (id) {
|
||||
case "bda-qem-twitch":
|
||||
twitch.addClass("active");
|
||||
$("#bda-qem-twitch-container").show();
|
||||
break;
|
||||
case "bda-qem-favourite":
|
||||
fav.addClass("active");
|
||||
$("#bda-qem-favourite-container").show();
|
||||
break;
|
||||
case "bda-qem-emojis":
|
||||
emojis.addClass("active");
|
||||
$(".emojiPicker-3m1S-j").show();
|
||||
$(".emojiPicker-3m1S-j .search-bar-inner input, .emojiPicker-3m1S-j .search-bar-inner input").focus();
|
||||
break;
|
||||
}
|
||||
this.lastTab = id;
|
||||
|
||||
const emoteIcon = $(".emote-icon");
|
||||
emoteIcon.off();
|
||||
emoteIcon.on("click", function () {
|
||||
const emote = $(this).attr("title");
|
||||
const ta = Utilities.getTextArea();
|
||||
Utilities.insertText(ta[0], ta.val().slice(-1) == " " ? ta.val() + emote : ta.val() + " " + emote);
|
||||
});
|
||||
};
|
||||
|
||||
QuickEmoteMenu.prototype.obsCallback = function (elem) {
|
||||
if (!this.initialized) return;
|
||||
const e = $(elem);
|
||||
if (!SettingsCookie["bda-es-9"]) {
|
||||
e.addClass("bda-qme-hidden");
|
||||
}
|
||||
else {
|
||||
e.removeClass("bda-qme-hidden");
|
||||
}
|
||||
|
||||
if (!SettingsCookie["bda-es-0"]) return;
|
||||
|
||||
e.prepend(this.qmeHeader);
|
||||
e.append(this.teContainer);
|
||||
e.append(this.faContainer);
|
||||
|
||||
if (this.lastTab == undefined) {
|
||||
this.lastTab = "bda-qem-emojis";
|
||||
}
|
||||
this.switchQem(this.lastTab);
|
||||
};
|
||||
|
||||
QuickEmoteMenu.prototype.favorite = function (name, url) {
|
||||
|
||||
if (!this.favoriteEmotes.hasOwnProperty(name)) {
|
||||
this.favoriteEmotes[name] = url;
|
||||
}
|
||||
|
||||
this.updateFavorites();
|
||||
};
|
||||
|
||||
QuickEmoteMenu.prototype.updateFavorites = function () {
|
||||
|
||||
let faContainer = "";
|
||||
faContainer += "<div id=\"bda-qem-favourite-container\">";
|
||||
faContainer += " <div class=\"scroller-wrap scrollerWrap-2lJEkd fade\">";
|
||||
faContainer += " <div class=\"scroller scroller-2FKFPG\">";
|
||||
faContainer += " <div class=\"emote-menu-inner\">";
|
||||
for (const emote in this.favoriteEmotes) {
|
||||
const url = this.favoriteEmotes[emote];
|
||||
faContainer += "<div class=\"emote-container\">";
|
||||
faContainer += " <img class=\"emote-icon\" alt=\"\" src=\"" + url + "\" title=\"" + emote + "\" oncontextmenu=\"quickEmoteMenu.favContext(event, this);\">";
|
||||
faContainer += " </img>";
|
||||
faContainer += "</div>";
|
||||
}
|
||||
faContainer += " </div>";
|
||||
faContainer += " </div>";
|
||||
faContainer += " </div>";
|
||||
faContainer += "</div>";
|
||||
this.faContainer = faContainer;
|
||||
|
||||
$("#bda-qem-favourite-container").replaceWith(faContainer);
|
||||
DataStore.setBDData("bdfavemotes", btoa(JSON.stringify(this.favoriteEmotes)));
|
||||
};
|
||||
|
||||
export default new QuickEmoteMenu();
|
|
@ -5,6 +5,7 @@ import BDEmote from "../ui/emote";
|
|||
import BdApi from "./pluginapi";
|
||||
import DataStore from "./datastore";
|
||||
import {DiscordModules} from "./webpackmodules";
|
||||
import {Toasts} from "ui";
|
||||
|
||||
const bdEmoteSettingIDs = {
|
||||
TwitchGlobal: "bda-es-7",
|
||||
|
@ -192,7 +193,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
|
|||
const exists = _fs.existsSync(file);
|
||||
|
||||
if (exists && this.isCacheValid()) {
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("Loading emotes from cache.", {type: "info"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show("Loading emotes from cache.", {type: "info"});
|
||||
Utilities.log("Emotes", "Loading emotes from local cache.");
|
||||
|
||||
const data = await new Promise(resolve => {
|
||||
|
@ -211,7 +212,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
|
|||
}
|
||||
|
||||
if (isValid) {
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("Emotes successfully loaded.", {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show("Emotes successfully loaded.", {type: "success"});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -220,7 +221,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
|
|||
}
|
||||
|
||||
if (!SettingsCookie["fork-es-3"]) return;
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("Downloading emotes in the background do not reload.", {type: "info"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show("Downloading emotes in the background do not reload.", {type: "info"});
|
||||
|
||||
for (const e in emoteInfo) {
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
|
@ -228,7 +229,7 @@ EmoteModule.prototype.loadEmoteData = async function(emoteInfo) {
|
|||
Emotes[emoteInfo[e].variable] = data;
|
||||
}
|
||||
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast("All emotes successfully downloaded.", {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show("All emotes successfully downloaded.", {type: "success"});
|
||||
|
||||
try { _fs.writeFileSync(file, JSON.stringify(Emotes), "utf8"); }
|
||||
catch (err) { Utilities.err("Emotes", "Could not save emote data.", err); }
|
||||
|
|
|
@ -11,7 +11,6 @@ import ContentManager from "./contentmanager";
|
|||
import DataStore from "./datastore";
|
||||
// import DevMode from "./devmode";
|
||||
import Events from "./emitter";
|
||||
import EmoteMenu from "./emotemenu";
|
||||
import EmoteModule from "./emotes";
|
||||
import PluginManager from "./pluginmanager";
|
||||
// import PublicServers from "./publicservers";
|
||||
|
@ -21,7 +20,7 @@ export const React = DiscordModules.React;
|
|||
export const ReactDOM = DiscordModules.ReactDOM;
|
||||
|
||||
export {BDV2, BdApi, Core, ContentManager, DataStore,
|
||||
Events, EmoteMenu, EmoteModule, PluginManager, /*PublicServers,*/ ThemeManager,
|
||||
Events, EmoteModule, PluginManager, /*PublicServers,*/ ThemeManager,
|
||||
Utilities, WebpackModules, DiscordModules};
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Plugins, SettingsCookie, PluginCookie, ThemeCookie} from "data";
|
|||
import Utilities from "./utilities";
|
||||
import WebpackModules, {DiscordModules} from "./webpackmodules";
|
||||
import DataStore from "./datastore";
|
||||
import Core from "./core";
|
||||
import {Toasts, Modals} from "ui";
|
||||
|
||||
const BdApi = {
|
||||
get React() { return DiscordModules.React; },
|
||||
|
@ -76,28 +76,13 @@ BdApi.getPlugin = function (name) {
|
|||
return null;
|
||||
};
|
||||
|
||||
|
||||
//Get BetterDiscord Core
|
||||
BdApi.getCore = function () {
|
||||
return Core;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a generic but very customizable modal.
|
||||
* @param {string} title - title of the modal
|
||||
* @param {string} content - a string of text to display in the modal
|
||||
*/
|
||||
BdApi.alert = function (title, content) {
|
||||
const ModalStack = BdApi.findModuleByProps("push", "update", "pop", "popWithKey");
|
||||
const AlertModal = BdApi.findModuleByPrototypes("handleCancel", "handleSubmit", "handleMinorConfirm");
|
||||
if (!ModalStack || !AlertModal) return Core.alert(title, content);
|
||||
|
||||
ModalStack.push(function(props) {
|
||||
return BdApi.React.createElement(AlertModal, Object.assign({
|
||||
title: title,
|
||||
body: content,
|
||||
}, props));
|
||||
});
|
||||
Modals.alert(title, content);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -112,33 +97,12 @@ BdApi.alert = function (title, content) {
|
|||
* @param {callable} [options.onCancel=NOOP] - callback to occur when clicking the cancel button
|
||||
*/
|
||||
BdApi.showConfirmationModal = function (title, content, options = {}) {
|
||||
const ModalStack = BdApi.findModuleByProps("push", "update", "pop", "popWithKey");
|
||||
const TextElement = BdApi.findModuleByProps("Sizes", "Weights");
|
||||
const ConfirmationModal = BdApi.findModule(m => m.defaultProps && m.key && m.key() == "confirm-modal");
|
||||
if (!ModalStack || !ConfirmationModal || !TextElement) return Core.alert(title, content);
|
||||
|
||||
const {onConfirm, onCancel, confirmText, cancelText, danger = false} = options;
|
||||
if (typeof(content) == "string") content = TextElement({color: TextElement.Colors.PRIMARY, children: [content]});
|
||||
else if (Array.isArray(content)) content = TextElement({color: TextElement.Colors.PRIMARY, children: content});
|
||||
content = [content];
|
||||
|
||||
const emptyFunction = () => {};
|
||||
ModalStack.push(function(props) {
|
||||
return BdApi.React.createElement(ConfirmationModal, Object.assign({
|
||||
header: title,
|
||||
children: content,
|
||||
red: danger,
|
||||
confirmText: confirmText ? confirmText : "Okay",
|
||||
cancelText: cancelText ? cancelText : "Cancel",
|
||||
onConfirm: onConfirm ? onConfirm : emptyFunction,
|
||||
onCancel: onCancel ? onCancel : emptyFunction
|
||||
}, props));
|
||||
});
|
||||
return Modals.showConfirmationModal(title, content, options);
|
||||
};
|
||||
|
||||
//Show toast alert
|
||||
BdApi.showToast = function(content, options = {}) {
|
||||
Core.showToast(content, options);
|
||||
Toasts.show(content, options);
|
||||
};
|
||||
|
||||
// Finds module
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import {SettingsCookie, PluginCookie, Plugins} from "data";
|
||||
import ContentManager from "./contentmanager";
|
||||
import Utilities from "./utilities";
|
||||
import Core from "./core";
|
||||
import BdApi from "./pluginapi";
|
||||
import Emitter from "./emitter";
|
||||
import DataStore from "./datastore";
|
||||
import {Toasts, Modals} from "ui";
|
||||
|
||||
function PluginModule() {
|
||||
|
||||
|
@ -34,7 +33,7 @@ PluginModule.prototype.loadPlugins = function () {
|
|||
if (PluginCookie[name]) {
|
||||
try {
|
||||
plugin.start();
|
||||
if (SettingsCookie["fork-ps-2"]) Core.showToast(`${plugin.getName()} v${plugin.getVersion()} has started.`);
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${plugin.getName()} v${plugin.getVersion()} has started.`);
|
||||
}
|
||||
catch (err) {
|
||||
PluginCookie[name] = false;
|
||||
|
@ -53,10 +52,10 @@ PluginModule.prototype.loadPlugins = function () {
|
|||
PluginModule.prototype.startPlugin = function(plugin, reload = false) {
|
||||
try {
|
||||
Plugins[plugin].plugin.start();
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} has started.`);
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Toasts.show(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} has started.`);
|
||||
}
|
||||
catch (err) {
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} could not be started.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Toasts.show(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} could not be started.`, {type: "error"});
|
||||
PluginCookie[plugin] = false;
|
||||
this.savePluginData();
|
||||
Utilities.err("Plugins", plugin + " could not be started.", err);
|
||||
|
@ -66,10 +65,10 @@ PluginModule.prototype.startPlugin = function(plugin, reload = false) {
|
|||
PluginModule.prototype.stopPlugin = function(plugin, reload = false) {
|
||||
try {
|
||||
Plugins[plugin].plugin.stop();
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} has stopped.`);
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Toasts.show(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} has stopped.`);
|
||||
}
|
||||
catch (err) {
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} could not be stopped.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Toasts.show(`${Plugins[plugin].plugin.getName()} v${Plugins[plugin].plugin.getVersion()} could not be stopped.`, {type: "error"});
|
||||
Utilities.err("Plugins", Plugins[plugin].plugin.getName() + " could not be stopped.", err);
|
||||
}
|
||||
};
|
||||
|
@ -96,15 +95,15 @@ PluginModule.prototype.togglePlugin = function (plugin) {
|
|||
PluginModule.prototype.loadPlugin = function(filename) {
|
||||
const error = ContentManager.loadContent(filename, "plugin");
|
||||
if (error) {
|
||||
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${filename} could not be loaded.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({plugins: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${filename} could not be loaded.`, {type: "error"});
|
||||
return Utilities.err("ContentManager", `${filename} could not be loaded.`, error);
|
||||
}
|
||||
const plugin = Object.values(Plugins).find(p => p.filename == filename).plugin;
|
||||
try { if (plugin.load && typeof(plugin.load) == "function") plugin.load();}
|
||||
catch (err) {if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [err]});}
|
||||
catch (err) {if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({plugins: [err]});}
|
||||
Utilities.log("ContentManager", `${plugin.getName()} v${plugin.getVersion()} was loaded.`);
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin.getName()} v${plugin.getVersion()} was loaded.`, {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${plugin.getName()} v${plugin.getVersion()} was loaded.`, {type: "success"});
|
||||
Emitter.dispatch("plugin-loaded", plugin.getName());
|
||||
};
|
||||
|
||||
|
@ -116,12 +115,12 @@ PluginModule.prototype.unloadPlugin = function(filenameOrName) {
|
|||
const error = ContentManager.unloadContent(Plugins[plugin].filename, "plugin");
|
||||
delete Plugins[plugin];
|
||||
if (error) {
|
||||
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({plugins: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${plugin} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
|
||||
return Utilities.err("ContentManager", `${plugin} could not be unloaded. It may have not been loaded yet.`, error);
|
||||
}
|
||||
Utilities.log("ContentManager", `${plugin} was unloaded.`);
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} was unloaded.`, {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${plugin} was unloaded.`, {type: "success"});
|
||||
Emitter.dispatch("plugin-unloaded", plugin);
|
||||
};
|
||||
|
||||
|
@ -133,14 +132,14 @@ PluginModule.prototype.reloadPlugin = function(filenameOrName) {
|
|||
if (enabled) this.stopPlugin(plugin, true);
|
||||
const error = ContentManager.reloadContent(Plugins[plugin].filename, "plugin");
|
||||
if (error) {
|
||||
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({plugins: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} could not be reloaded.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({plugins: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${plugin} could not be reloaded.`, {type: "error"});
|
||||
return Utilities.err("ContentManager", `${plugin} could not be reloaded.`, error);
|
||||
}
|
||||
if (Plugins[plugin].plugin.load && typeof(Plugins[plugin].plugin.load) == "function") Plugins[plugin].plugin.load();
|
||||
if (enabled) this.startPlugin(plugin, true);
|
||||
Utilities.log("ContentManager", `${plugin} v${Plugins[plugin].plugin.getVersion()} was reloaded.`);
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${plugin} v${Plugins[plugin].plugin.getVersion()} was reloaded.`, {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${plugin} v${Plugins[plugin].plugin.getVersion()} was reloaded.`, {type: "success"});
|
||||
Emitter.dispatch("plugin-reloaded", plugin);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import {SettingsCookie} from "data";
|
||||
// import ClassNormalizer from "./classnormalizer";
|
||||
import DataStore from "./datastore";
|
||||
import ContentManager from "./contentmanager";
|
||||
import BdApi from "./pluginapi";
|
||||
import Core from "./core";
|
||||
import EmoteModule from "./emotes";
|
||||
// import DevMode from "./devmode";
|
||||
import Events from "./emitter";
|
||||
import WebpackModules from "./webpackmodules";
|
||||
|
||||
import {SettingsPanel as SettingsRenderer} from "ui";
|
||||
import Utilities from "./utilities";
|
||||
|
||||
//WebpackModules.getModule(m => m.getSection && m.getProps && !m.getGuildId && !m.getChannel)
|
||||
//WebpackModules.getByProps("getGuildId", "getSection")
|
||||
|
||||
export default new class SettingsPanel {
|
||||
|
||||
|
@ -19,6 +22,62 @@ export default new class SettingsPanel {
|
|||
this.renderer.renderSidebar();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
DataStore.initialize();
|
||||
if (!DataStore.getSettingGroup("settings")) return this.saveSettings();
|
||||
const savedSettings = this.loadSettings();
|
||||
$("<style id=\"customcss\">").text(atob(DataStore.getBDData("bdcustomcss"))).appendTo(document.head);
|
||||
for (const setting in savedSettings) {
|
||||
if (savedSettings[setting] !== undefined) SettingsCookie[setting] = savedSettings[setting];
|
||||
}
|
||||
this.saveSettings();
|
||||
// console.log("PATCHING");
|
||||
// Utilities.monkeyPatch(WebpackModules.getByProps("getUserSettingsSections").default.prototype, "render", {after: (data) => {
|
||||
// data.returnValue.type;
|
||||
// }});
|
||||
|
||||
// Patcher.after(temp2.prototype, "generateSections", (t,a,r) => {
|
||||
// r.push({section: "DIVIDER"});
|
||||
// r.push({section: "HEADER", label: "My Section"});
|
||||
// r.push({color: "#ffffff", label: "My Tab", onClick: function() {console.log("CLICK");}, section: "My Section"});
|
||||
// r.push({color: "#cccccc", label: "My Tab2", onClick: function() {console.log("CLICK2");}, section: "My Section"});
|
||||
|
||||
// })
|
||||
this.patchSections();
|
||||
}
|
||||
|
||||
async patchSections() {
|
||||
const UserSettings = await this.getUserSettings(); // data.returnValue.type;
|
||||
Utilities.monkeyPatch(UserSettings.prototype, "generateSections", {after: (data) => {
|
||||
console.log(data);
|
||||
data.returnValue.splice(23, 0, {section: "DIVIDER"});
|
||||
data.returnValue.splice(24, 0, {section: "HEADER", label: "BandagedBD"});
|
||||
data.returnValue.splice(25, 0, {section: "IJ1", label: "Injected Tab 1", element: () => this.renderer.core2});
|
||||
data.returnValue.splice(26, 0, {section: "IJ2", label: "Injected Tab 2", onClick: function() {console.log("CLICK2");}});
|
||||
}});
|
||||
const viewClass = WebpackModules.getByProps("standardSidebarView").standardSidebarView.split(" ")[0];
|
||||
const node = document.querySelector(`.${viewClass}`);
|
||||
Utilities.getInternalInstance(node).return.return.return.return.return.return.stateNode.forceUpdate();
|
||||
}
|
||||
|
||||
getUserSettings() {
|
||||
return new Promise(resolve => {
|
||||
const cancel = Utilities.monkeyPatch(WebpackModules.getByProps("getUserSettingsSections").default.prototype, "render", {after: (data) => {
|
||||
resolve(data.returnValue.type);
|
||||
data.thisObject.forceUpdate();
|
||||
cancel();
|
||||
}});
|
||||
});
|
||||
}
|
||||
|
||||
saveSettings() {
|
||||
DataStore.setSettingGroup("settings", SettingsCookie);
|
||||
}
|
||||
|
||||
loadSettings() {
|
||||
return DataStore.getSettingGroup("settings");
|
||||
}
|
||||
|
||||
updateSettings(id, enabled) {
|
||||
Events.dispatch("setting-updated", "Modules", id, enabled);
|
||||
SettingsCookie[id] = enabled;
|
||||
|
@ -46,7 +105,7 @@ export default new class SettingsPanel {
|
|||
else BdApi.setWindowPreference("backgroundColor", "#2f3136");
|
||||
}
|
||||
|
||||
Core.saveSettings();
|
||||
this.saveSettings();
|
||||
}
|
||||
|
||||
initializeSettings() {
|
||||
|
@ -57,6 +116,6 @@ export default new class SettingsPanel {
|
|||
ContentManager.watchContent("theme");
|
||||
}
|
||||
|
||||
Core.saveSettings();
|
||||
this.saveSettings();
|
||||
}
|
||||
};
|
|
@ -1,10 +1,9 @@
|
|||
import {SettingsCookie, ThemeCookie, Themes} from "data";
|
||||
import ContentManager from "./contentmanager";
|
||||
import Utilities from "./utilities";
|
||||
import Core from "./core";
|
||||
import BdApi from "./pluginapi";
|
||||
import Emitter from "./emitter";
|
||||
import DataStore from "./datastore";
|
||||
import {Toasts, Modals} from "ui";
|
||||
|
||||
function ThemeModule() {
|
||||
|
||||
|
@ -32,14 +31,14 @@ ThemeModule.prototype.enableTheme = function(theme, reload = false) {
|
|||
ThemeCookie[theme] = true;
|
||||
this.saveThemeData();
|
||||
$("head").append($("<style>", {id: Utilities.escapeID(theme), text: unescape(Themes[theme].css)}));
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Themes[theme].name} v${Themes[theme].version} has been applied.`);
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Toasts.show(`${Themes[theme].name} v${Themes[theme].version} has been applied.`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.disableTheme = function(theme, reload = false) {
|
||||
ThemeCookie[theme] = false;
|
||||
this.saveThemeData();
|
||||
$(`#${Utilities.escapeID(Themes[theme].name)}`).remove();
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Core.showToast(`${Themes[theme].name} v${Themes[theme].version} has been disabled.`);
|
||||
if (SettingsCookie["fork-ps-2"] && !reload) Toasts.show(`${Themes[theme].name} v${Themes[theme].version} has been disabled.`);
|
||||
};
|
||||
|
||||
ThemeModule.prototype.toggleTheme = function(theme) {
|
||||
|
@ -50,13 +49,13 @@ ThemeModule.prototype.toggleTheme = function(theme) {
|
|||
ThemeModule.prototype.loadTheme = function(filename) {
|
||||
const error = ContentManager.loadContent(filename, "theme");
|
||||
if (error) {
|
||||
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({themes: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${filename} could not be loaded. It may not have been loaded.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({themes: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${filename} could not be loaded. It may not have been loaded.`, {type: "error"});
|
||||
return Utilities.err("ContentManager", `${filename} could not be loaded.`, error);
|
||||
}
|
||||
const theme = Object.values(Themes).find(p => p.filename == filename);
|
||||
Utilities.log("ContentManager", `${theme.name} v${theme.version} was loaded.`);
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme.name} v${theme.version} was loaded.`, {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${theme.name} v${theme.version} was loaded.`, {type: "success"});
|
||||
Emitter.dispatch("theme-loaded", theme.name);
|
||||
};
|
||||
|
||||
|
@ -68,12 +67,12 @@ ThemeModule.prototype.unloadTheme = function(filenameOrName) {
|
|||
const error = ContentManager.unloadContent(Themes[theme].filename, "theme");
|
||||
delete Themes[theme];
|
||||
if (error) {
|
||||
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({themes: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({themes: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${theme} could not be unloaded. It may have not been loaded yet.`, {type: "error"});
|
||||
return Utilities.err("ContentManager", `${theme} could not be unloaded. It may have not been loaded yet.`, error);
|
||||
}
|
||||
Utilities.log("ContentManager", `${theme} was unloaded.`);
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} was unloaded.`, {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${theme} was unloaded.`, {type: "success"});
|
||||
Emitter.dispatch("theme-unloaded", theme);
|
||||
};
|
||||
|
||||
|
@ -84,12 +83,12 @@ ThemeModule.prototype.reloadTheme = function(filenameOrName) {
|
|||
const error = ContentManager.reloadContent(Themes[theme].filename, "theme");
|
||||
if (ThemeCookie[theme]) this.disableTheme(theme, true), this.enableTheme(theme, true);
|
||||
if (error) {
|
||||
if (SettingsCookie["fork-ps-1"]) Core.showContentErrors({themes: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} could not be reloaded.`, {type: "error"});
|
||||
if (SettingsCookie["fork-ps-1"]) Modals.showContentErrors({themes: [error]});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${theme} could not be reloaded.`, {type: "error"});
|
||||
return Utilities.err("ContentManager", `${theme} could not be reloaded.`, error);
|
||||
}
|
||||
Utilities.log("ContentManager", `${theme} v${Themes[theme].version} was reloaded.`);
|
||||
if (SettingsCookie["fork-ps-2"]) BdApi.showToast(`${theme} v${Themes[theme].version} was reloaded.`, {type: "success"});
|
||||
if (SettingsCookie["fork-ps-2"]) Toasts.show(`${theme} v${Themes[theme].version} was reloaded.`, {type: "success"});
|
||||
Emitter.dispatch("theme-reloaded", theme);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {SettingsCookie} from "data";
|
||||
import {BDV2, EmoteMenu, DiscordModules} from "modules";
|
||||
import {BDV2, DiscordModules} from "modules";
|
||||
import EmoteMenu from "../builtins/emotemenu";
|
||||
|
||||
export default class BDEmote extends DiscordModules.React.Component {
|
||||
constructor(props) {
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
import {Utilities, WebpackModules, React} from "modules";
|
||||
|
||||
export default class Modals {
|
||||
|
||||
static get ModalStack() {return WebpackModules.getByProps("push", "update", "pop", "popWithKey");}
|
||||
static get AlertModal() {return WebpackModules.getByPrototypes("handleCancel", "handleSubmit", "handleMinorConfirm");}
|
||||
static get TextElement() {return WebpackModules.getByProps("Sizes", "Weights");}
|
||||
static get ConfirmationModal() {return WebpackModules.getModule(m => m.defaultProps && m.key && m.key() == "confirm-modal");}
|
||||
|
||||
static default(title, content) {
|
||||
const modal = $(`<div class="bd-modal-wrapper theme-dark">
|
||||
<div class="bd-backdrop backdrop-1wrmKB"></div>
|
||||
<div class="bd-modal modal-1UGdnR">
|
||||
<div class="bd-modal-inner inner-1JeGVc">
|
||||
<div class="header header-1R_AjF">
|
||||
<div class="title">${title}</div>
|
||||
</div>
|
||||
<div class="bd-modal-body">
|
||||
<div class="scroller-wrap fade">
|
||||
<div class="scroller">
|
||||
${content}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer footer-2yfCgX">
|
||||
<button type="button">Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
modal.find(".footer button").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.find(".bd-backdrop").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.appendTo("#app-mount");
|
||||
}
|
||||
|
||||
static alert(title, content) {
|
||||
if (this.ModalStack && this.AlertModal) return this.default(title, content);
|
||||
this.ModalStack.push(function(props) {
|
||||
return React.createElement(this.AlertModal, Object.assign({
|
||||
title: title,
|
||||
body: content,
|
||||
}, props));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a generic but very customizable confirmation modal with optional confirm and cancel callbacks.
|
||||
* @param {string} title - title of the modal
|
||||
* @param {(string|ReactElement|Array<string|ReactElement>)} children - a single or mixed array of react elements and strings. Everything is wrapped in Discord's `TextElement` component so strings will show and render properly.
|
||||
* @param {object} [options] - options to modify the modal
|
||||
* @param {boolean} [options.danger=false] - whether the main button should be red or not
|
||||
* @param {string} [options.confirmText=Okay] - text for the confirmation/submit button
|
||||
* @param {string} [options.cancelText=Cancel] - text for the cancel button
|
||||
* @param {callable} [options.onConfirm=NOOP] - callback to occur when clicking the submit button
|
||||
* @param {callable} [options.onCancel=NOOP] - callback to occur when clicking the cancel button
|
||||
*/
|
||||
static showConfirmationModal(title, content, options = {}) {
|
||||
const TextElement = this.TextElement;
|
||||
const ConfirmationModal = this.ConfirmationModal;
|
||||
const ModalStack = this.ModalStack;
|
||||
if (!this.ModalStack || !this.ConfirmationModal || !this.TextElement) return this.alert(title, content);
|
||||
|
||||
const {onConfirm, onCancel, confirmText, cancelText, danger = false} = options;
|
||||
if (typeof(content) == "string") content = TextElement({color: TextElement.Colors.PRIMARY, children: [content]});
|
||||
else if (Array.isArray(content)) content = TextElement({color: TextElement.Colors.PRIMARY, children: content});
|
||||
content = [content];
|
||||
|
||||
const emptyFunction = () => {};
|
||||
ModalStack.push(function(props) {
|
||||
return React.createElement(ConfirmationModal, Object.assign({
|
||||
header: title,
|
||||
children: content,
|
||||
red: danger,
|
||||
confirmText: confirmText ? confirmText : "Okay",
|
||||
cancelText: cancelText ? cancelText : "Cancel",
|
||||
onConfirm: onConfirm ? onConfirm : emptyFunction,
|
||||
onCancel: onCancel ? onCancel : emptyFunction
|
||||
}, props));
|
||||
});
|
||||
}
|
||||
|
||||
static showContentErrors({plugins: pluginErrors = [], themes: themeErrors = []}) {
|
||||
if (!pluginErrors || !themeErrors) return;
|
||||
if (!pluginErrors.length && !themeErrors.length) return;
|
||||
const modal = $(`<div class="bd-modal-wrapper theme-dark">
|
||||
<div class="bd-backdrop backdrop-1wrmKB"></div>
|
||||
<div class="bd-modal bd-content-modal modal-1UGdnR">
|
||||
<div class="bd-modal-inner inner-1JeGVc">
|
||||
<div class="header header-1R_AjF"><div class="title">Content Errors</div></div>
|
||||
<div class="bd-modal-body">
|
||||
<div class="tab-bar-container">
|
||||
<div class="tab-bar TOP">
|
||||
<div class="tab-bar-item">Plugins</div>
|
||||
<div class="tab-bar-item">Themes</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-header">
|
||||
<div class="table-column column-name">Name</div>
|
||||
<div class="table-column column-message">Message</div>
|
||||
<div class="table-column column-error">Error</div>
|
||||
</div>
|
||||
<div class="scroller-wrap fade">
|
||||
<div class="scroller">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer footer-2yfCgX">
|
||||
<button type="button">Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
|
||||
const generateTab = function(errors) {
|
||||
const container = $(`<div class="errors">`);
|
||||
for (const err of errors) {
|
||||
const error = $(`<div class="error">
|
||||
<div class="table-column column-name">${err.name ? err.name : err.file}</div>
|
||||
<div class="table-column column-message">${err.message}</div>
|
||||
<div class="table-column column-error"><a class="error-link" href="">${err.error ? err.error.message : ""}</a></div>
|
||||
</div>`);
|
||||
container.append(error);
|
||||
if (err.error) {
|
||||
error.find("a").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
Utilities.err("ContentManager", `Error details for ${err.name ? err.name : err.file}.`, err.error);
|
||||
});
|
||||
}
|
||||
}
|
||||
return container;
|
||||
};
|
||||
|
||||
const tabs = [generateTab(pluginErrors), generateTab(themeErrors)];
|
||||
|
||||
modal.find(".tab-bar-item").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
modal.find(".tab-bar-item").removeClass("selected");
|
||||
$(e.target).addClass("selected");
|
||||
modal.find(".scroller").empty().append(tabs[$(e.target).index()]);
|
||||
});
|
||||
|
||||
modal.find(".footer button").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.find(".bd-backdrop").on("click", () => {
|
||||
modal.addClass("closing");
|
||||
setTimeout(() => { modal.remove(); }, 300);
|
||||
});
|
||||
modal.appendTo("#app-mount");
|
||||
if (pluginErrors.length) modal.find(".tab-bar-item")[0].click();
|
||||
else modal.find(".tab-bar-item")[1].click();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import {SettingsInfo, SettingsCookie, Plugins, Themes} from "data";
|
||||
import {React, ReactDOM, Utilities, ContentManager, Events, EmoteModule, EmoteMenu, PluginManager, ThemeManager} from "modules";
|
||||
import {React, ReactDOM, Utilities, ContentManager, Events, EmoteModule, PluginManager, ThemeManager} from "modules";
|
||||
import Sidebar from "./sidebar";
|
||||
import Scroller from "../scroller";
|
||||
import List from "../list";
|
||||
|
@ -12,6 +12,7 @@ import ThemeCard from "./themecard";
|
|||
import ReloadIcon from "../icons/reload";
|
||||
|
||||
import CssEditor from "../customcss/editor";
|
||||
import SettingsGroup from "../settings/settingsgroup";
|
||||
|
||||
export default class V2_SettingsPanel {
|
||||
|
||||
|
@ -98,6 +99,12 @@ export default class V2_SettingsPanel {
|
|||
self.sidebar.render();
|
||||
}
|
||||
|
||||
get core2() {
|
||||
return this.coreSettings.map(section => {
|
||||
return React.createElement(SettingsGroup, Object.assign({}, section, {onChange: this.onChange}));
|
||||
});
|
||||
}
|
||||
|
||||
get coreComponent() {
|
||||
return React.createElement(Scroller, {contentColumn: true, fade: true, dark: true, children: [
|
||||
React.createElement(SectionedSettingsPanel, {key: "cspanel", onChange: this.onChange, sections: this.coreSettings}),
|
||||
|
@ -110,7 +117,7 @@ export default class V2_SettingsPanel {
|
|||
contentColumn: true, fade: true, dark: true, children: [
|
||||
React.createElement(SettingsPanel, {key: "espanel", title: "Emote Settings", onChange: this.onChange, settings: this.emoteSettings, button: {
|
||||
title: "Clear Emote Cache",
|
||||
onClick: () => { EmoteModule.clearEmoteData(); EmoteModule.init(); EmoteMenu.init(); }
|
||||
onClick: () => { EmoteModule.clearEmoteData(); EmoteModule.init(); }
|
||||
}}),
|
||||
React.createElement(Tools, {key: "tools"})
|
||||
]});
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
import {React} from "modules";
|
||||
|
||||
const flexContainer = "flex-1xMQg5 flex-1O1GKY da-flex da-flex vertical-V37hAW flex-1O1GKY directionColumn-35P_nr justifyStart-2NDFzi alignStretch-DpGPf3 noWrap-3jynv6 switchItem-2hKKKK";
|
||||
const flexWrap = "flex-1xMQg5 flex-1O1GKY da-flex da-flex horizontal-1ae9ci horizontal-2EEEnY flex-1O1GKY directionRow-3v3tfG justifyStart-2NDFzi alignStart-H-X2h- noWrap-3jynv6";
|
||||
const flexChild = "flexChild-faoVW3 da-flexChild";
|
||||
const title = "titleDefault-a8-ZSr title-31JmR4 da-titleDefault da-title";
|
||||
const switchWrapper = "flexChild-faoVW3 da-flexChild switchEnabled-V2WDBB switch-3wwwcV da-switchEnabled da-switch valueUnchecked-2lU_20 value-2hFrkk sizeDefault-2YlOZr size-3rFEHg themeDefault-24hCdX";
|
||||
const switchWrapperEnabled = "flexChild-faoVW3 da-flexChild switchEnabled-V2WDBB switch-3wwwcV da-switchEnabled da-switch valueChecked-m-4IJZ value-2hFrkk sizeDefault-2YlOZr size-3rFEHg themeDefault-24hCdX";
|
||||
const switchClass = "checkboxEnabled-CtinEn checkbox-2tyjJg da-checkboxEnabled da-checkbox";
|
||||
const description = "description-3_Ncsb formText-3fs7AJ da-description da-formText note-1V3kyJ da-note modeDefault-3a2Ph1 da-modeDefault primary-jw0I4K";
|
||||
|
||||
export default class V2C_Switch extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
|
@ -19,25 +28,25 @@ export default class V2C_Switch extends React.Component {
|
|||
const {checked} = this.state;
|
||||
return React.createElement(
|
||||
"div",
|
||||
{className: "ui-flex flex-vertical flex-justify-start flex-align-stretch flex-nowrap ui-switch-item"},
|
||||
{className: `ui-flex flex-vertical flex-justify-start flex-align-stretch flex-nowrap ui-switch-item ${flexContainer}`},
|
||||
React.createElement(
|
||||
"div",
|
||||
{className: "ui-flex flex-horizontal flex-justify-start flex-align-stretch flex-nowrap"},
|
||||
{className: `ui-flex flex-horizontal flex-justify-start flex-align-stretch flex-nowrap ${flexWrap}`},
|
||||
React.createElement(
|
||||
"h3",
|
||||
{className: "ui-form-title h3 margin-reset margin-reset ui-flex-child"},
|
||||
{className: `ui-form-title h3 margin-reset margin-reset ui-flex-child ${title} ${flexChild}`},
|
||||
text
|
||||
),
|
||||
React.createElement(
|
||||
"label",
|
||||
{className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
|
||||
React.createElement("input", {className: "ui-switch-checkbox", type: "checkbox", checked: checked, onChange: e => this.onChange(e)}),
|
||||
"div",
|
||||
{className: `ui-switch-wrapper ui-flex-child ${checked ? switchWrapperEnabled : switchWrapper}`, style: {flex: "0 0 auto"}},
|
||||
React.createElement("input", {className: `ui-switch-checkbox ${switchClass}`, type: "checkbox", checked: checked, onChange: e => this.onChange(e)}),
|
||||
React.createElement("div", {className: `ui-switch ${checked ? "checked" : ""}`})
|
||||
)
|
||||
),
|
||||
React.createElement(
|
||||
"div",
|
||||
{className: "ui-form-text style-description margin-top-4", style: {flex: "1 1 auto"}},
|
||||
{className: `ui-form-text style-description margin-top-4 ${description}`, style: {flex: "1 1 auto"}},
|
||||
info
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {SettingsCookie, ThemeCookie, Themes} from "data";
|
||||
import {React, Core, ThemeManager} from "modules";
|
||||
import {React, ThemeManager} from "modules";
|
||||
import ReloadIcon from "../icons/reload";
|
||||
import Toasts from "../toasts";
|
||||
|
||||
export default class V2C_ThemeCard extends React.Component {
|
||||
|
||||
|
@ -34,8 +35,8 @@ export default class V2C_ThemeCard extends React.Component {
|
|||
reload() {
|
||||
const theme = this.props.theme.name;
|
||||
const error = ThemeManager.reloadTheme(theme);
|
||||
if (error) Core.showToast(`Could not reload ${Themes[theme].name}. Check console for details.`, {type: "error"});
|
||||
else Core.showToast(`${Themes[theme].name} v${Themes[theme].version} has been reloaded.`, {type: "success"});
|
||||
if (error) Toasts.show(`Could not reload ${Themes[theme].name}. Check console for details.`, {type: "error"});
|
||||
else Toasts.show(`${Themes[theme].name} v${Themes[theme].version} has been reloaded.`, {type: "success"});
|
||||
// this.setState(this.state);
|
||||
this.props.theme = Themes[theme];
|
||||
this.onReload(this.props.theme.name);
|
||||
|
|
|
@ -8,7 +8,7 @@ export default class V2C_SettingsTitle extends React.Component {
|
|||
render() {
|
||||
return React.createElement(
|
||||
"h2",
|
||||
{className: "ui-form-title h2 margin-reset margin-bottom-20 marginTop60-3PGbtK da-marginTop6"},
|
||||
{className: "ui-form-title h2 margin-reset margin-bottom-20 marginTop60-3PGbtK h2-2gWE-o title-3sZWYQ size16-14cGz5 height20-mO2eIN weightSemiBold-NJexzi defaultColor-1_ajX0 defaultMarginh2-2LTaUL marginBottom20-32qID7"},
|
||||
this.props.text
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
import {WebpackModules} from "modules";
|
||||
|
||||
const channelsClass = WebpackModules.getByProps("channels").channels.split(" ")[0];
|
||||
const membersWrapClass = WebpackModules.getByProps("membersWrap").membersWrap.split(" ")[0];
|
||||
|
||||
export default class Toasts {
|
||||
|
||||
/** Shorthand for `type = "success"` for {@link module:Toasts.show} */
|
||||
static async success(content, options = {}) {return this.show(content, Object.assign(options, {type: "success"}));}
|
||||
|
||||
/** Shorthand for `type = "info"` for {@link module:Toasts.show} */
|
||||
static async info(content, options = {}) {return this.show(content, Object.assign(options, {type: "info"}));}
|
||||
|
||||
/** Shorthand for `type = "warning"` for {@link module:Toasts.show} */
|
||||
static async warning(content, options = {}) {return this.show(content, Object.assign(options, {type: "warning"}));}
|
||||
|
||||
/** Shorthand for `type = "error"` for {@link module:Toasts.show} */
|
||||
static async error(content, options = {}) {return this.show(content, Object.assign(options, {type: "error"}));}
|
||||
|
||||
/** Shorthand for `type = "default"` for {@link module:Toasts.show} */
|
||||
static async default(content, options = {}) {return this.show(content, Object.assign(options, {type: ""}));}
|
||||
|
||||
/**
|
||||
* This shows a toast similar to android towards the bottom of the screen.
|
||||
*
|
||||
* @param {string} content The string to show in the toast.
|
||||
* @param {object} options Options object. Optional parameter.
|
||||
* @param {string} options.type Changes the type of the toast stylistically and semantically. Choices: "", "info", "success", "danger"/"error", "warning"/"warn". Default: ""
|
||||
* @param {boolean} options.icon Determines whether the icon should show corresponding to the type. A toast without type will always have no icon. Default: true
|
||||
* @param {number} options.timeout Adjusts the time (in ms) the toast should be shown for before disappearing automatically. Default: 3000
|
||||
*/
|
||||
static show(content, options = {}) {
|
||||
this.ensureContainer();
|
||||
const {type = "", icon = true, timeout = 3000} = options;
|
||||
const toastElem = document.createElement("div");
|
||||
toastElem.classList.add("bd-toast");
|
||||
if (type) toastElem.classList.add("toast-" + type);
|
||||
if (type && icon) toastElem.classList.add("icon");
|
||||
toastElem.innerText = content;
|
||||
document.querySelector(".bd-toasts").appendChild(toastElem);
|
||||
setTimeout(() => {
|
||||
toastElem.classList.add("closing");
|
||||
setTimeout(() => {
|
||||
toastElem.remove();
|
||||
if (!document.querySelectorAll(".bd-toasts .bd-toast").length) document.querySelector(".bd-toasts").remove();
|
||||
}, 300);
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
static ensureContainer() {
|
||||
if (document.querySelector(".bd-toasts")) return;
|
||||
const container = document.querySelector(`.${channelsClass} + div`);
|
||||
const memberlist = container.querySelector(`.${membersWrapClass}`);
|
||||
const form = container ? container.querySelector("form") : null;
|
||||
const left = container ? container.getBoundingClientRect().left : 310;
|
||||
const right = memberlist ? memberlist.getBoundingClientRect().left : 0;
|
||||
const width = right ? right - container.getBoundingClientRect().left : container.offsetWidth;
|
||||
const bottom = form ? form.offsetHeight : 80;
|
||||
const toastWrapper = document.createElement("div");
|
||||
toastWrapper.classList.add("bd-toasts");
|
||||
toastWrapper.style.setProperty("left", left + "px");
|
||||
toastWrapper.style.setProperty("width", width + "px");
|
||||
toastWrapper.style.setProperty("bottom", bottom + "px");
|
||||
document.querySelector("#app-mount").appendChild(toastWrapper);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import SettingsPanel from "./settings/settings";
|
||||
import * as PublicServers from "./publicservers/publicservers";
|
||||
|
||||
export {default as Toasts} from "./toasts";
|
||||
export {default as Modals} from "./modals";
|
||||
export {SettingsPanel, PublicServers};
|
Loading…
Reference in New Issue