//META{"name":"ServerFolders","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ServerFolders","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ServerFolders/ServerFolders.plugin.js"}*//
class ServerFolders {
getName () {return "ServerFolders";}
getVersion () {return "6.5.7";}
getAuthor () {return "DevilBro";}
getDescription () {return "Patches Discords native Folders in a way to open Servers within a Folder in a new bar to the right. Also adds a bunch of new features to more easily organize, customize and manage your Folders.";}
constructor () {
this.changelog = {
"improved":[["Native Folder Support","Yes, it's here finally. ServerFolders now uses native Folders to emulate the old ServerFolders behaviour. This means you can now finally organize your Servers in Folders the old way without loosing the support on your phone. Everything should be working as it's used to. Below is a list of stuff that is NEW"],["Folder Creation","Instead of creating a Folder with the targeted Server, a menu now opens that let's you select which Servers you want to add to the Folder before you create it"]],
"fixed":[["Fixed?","Added back the option to create a Folder via the contextmenu, the amount of people which won't know how to create native Folders is worrying"],["Theme Issues","Fixed some theme issues with themes like ClearVision"],["Settings","Some fixes with the closing behaviour settings"]]
};
this.labels = {};
this.patchModules = {
"Guilds":["componentDidMount","componentDidUpdate","componentWillUnmount"],
"GuildFolder":["componentDidMount","componentDidUpdate"],
"Guild":["componentDidMount","componentDidUpdate"],
"GuildFolderSettingsModal":"componentDidMount",
"StandardSidebarView":"componentWillUnmount"
};
}
initConstructor () {
this.folderStates = {};
this.folderReads = {};
this.guildStates = {};
this.css = `
.${this.name}-modal .ui-icon-picker-icon {
position: relative;
margin: 3px 3px;
padding: 3px 3px;
width: 55px;
height: 55px;
border-radius: 12px;
}
.${this.name}-modal .ui-icon-picker-icon .ui-picker-inner {
width: 100%;
height: 100%;
border-radius: 12px;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
.${this.name}-modal .ui-icon-picker-icon.selected ${BDFDB.dotCN.hovercardbutton} {
display: none !important;
}
.${this.name}-modal .ui-icon-picker-icon ${BDFDB.dotCN.hovercardbutton} {
position: absolute;
top: -10px;
right: -10px;
}
.${this.name}-modal .ui-icon-picker-icon.preview.nopic .ui-picker-inner {
background: url('data:image/svg+xml; utf8, ') center/cover no-repeat;
}
${BDFDB.dotCN.guildfolder}[style*="background-image"] {
background-color: transparent !important;
background-position: center !important;
background-size: cover !important;
background-repeat: no-repeat !important;
transiton: unset !important;
}
${BDFDB.dotCN.guildfolder}[style*="background-image"] ${BDFDB.dotCN.guildfoldericonwrapper},
${BDFDB.dotCN.guildfolderexpandendbackground},
${BDFDB.dotCN.guildfolderexpandedguilds} {
display: none !important;
}
${BDFDB.dotCN.guildupperbadge}.count {
left: 0px;
right: unset;
}
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview {
pointer-events: none !important;
position: absolute !important;
opacity: 0.5 !important;
z-index: 10000 !important;
}
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview,
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview ${BDFDB.dotCN.guildinner},
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview ${BDFDB.dotCNS.guildinner + BDFDB.dotCN.guildiconwrapper},
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview ${BDFDB.dotCNS.guildinner + BDFDB.dotCNS.guildiconwrapper + BDFDB.dotCN.guildicon} {
border-radius: 50% !important;
width: 48px !important;
height: 48px !important;
}
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview ${BDFDB.dotCN.guildpillwrapper} {
display: none !important;
}
${BDFDB.dotCN.guildouter}.serverfolders-dragpreview ${BDFDB.dotCN.guildiconacronym} {
color: white !important;
background-color: #444 !important;
border-radius: 50% !important;
overflow: hidden !important;
}
${BDFDB.dotCN.guildswrapper}.foldercontent {
transition: width .3s linear !important;
left: 72px;
}
${BDFDB.dotCN.guildswrapper}.foldercontent .folderseparatorouter {
margin-top: 10px;
}
${BDFDB.dotCN.guildswrapper}.foldercontent.foldercontentclosed {
width: 0px !important;
}
${BDFDB.dotCN.appcontainer} {
display: flex !important;
}
${BDFDB.dotCN.guildswrapper} {
position: static !important;
contain: unset !important;
}
${BDFDB.dotCN.chatbase} {
position: static !important;
contain: unset !important;
width: 100% !important;
}`;
this.folderContentMarkup =
`
`;
this.dragPlaceholderMarkup =
`
`;
this.folderIcons = [
{openicon:``,
closedicon:``},
{openicon:``,
closedicon:``},
{openicon:``,
closedicon:``},
{openicon:``,
closedicon:``},
{openicon:``,
closedicon:``},
{openicon:``,
closedicon:``},
{openicon:``,
closedicon:``}
];
this.defaults = {
settings: {
closeOtherFolders: {value:false, description:"Close other Folders when opening a Folder."},
closeTheFolder: {value:false, description:"Close the Folder when selecting a Server."},
closeAllFolders: {value:false, description:"Close All Folders when selecting a Server."},
forceOpenFolder: {value:false, description:"Force a Folder to open when switching to a Server of that Folder."},
showCountBadge: {value:true, description:"Display Badge for Amount of Servers in a Folder."},
addSeparators: {value:true, description:"Adds separators between Servers of different Folders."}
}
};
}
getSettingsPanel () {
if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return;
let settings = BDFDB.getAllData(this, "settings");
let settingshtml = `
${this.name}
`;
for (let key in settings) {
settingshtml += `
${this.defaults.settings[key].description}
`;
}
settingshtml += `
Remove all custom Icons.
`;
settingshtml += `
`;
let settingspanel = BDFDB.htmlToElement(settingshtml);
BDFDB.initElements(settingspanel, this);
BDFDB.addEventListener(this, settingspanel, "click", ".removecustom-button", () => {
BDFDB.openConfirmModal(this, "Are you sure you want to remove all custom icons?", () => {
BDFDB.removeAllData(this, "customicons");
});
});
return settingspanel;
}
//legacy
load () {}
start () {
if (!global.BDFDB) global.BDFDB = {myPlugins:{}};
if (global.BDFDB && global.BDFDB.myPlugins && typeof global.BDFDB.myPlugins == "object") global.BDFDB.myPlugins[this.getName()] = this;
var libraryScript = document.querySelector('head script#BDFDBLibraryScript');
if (!libraryScript || (performance.now() - libraryScript.getAttribute("date")) > 600000) {
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("id", "BDFDBLibraryScript");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
libraryScript.setAttribute("date", performance.now());
libraryScript.addEventListener("load", () => {this.initialize();});
document.head.appendChild(libraryScript);
this.libLoadTimeout = setTimeout(() => {
libraryScript.remove();
BDFDB.LibraryRequires.request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js", (error, response, body) => {
if (body) {
libraryScript = document.createElement("script");
libraryScript.setAttribute("id", "BDFDBLibraryScript");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("date", performance.now());
libraryScript.innerText = body;
document.head.appendChild(libraryScript);
}
this.initialize();
});
}, 15000);
}
else if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize();
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
}
initialize () {
if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) {
if (this.started) return;
BDFDB.loadMessage(this);
// REMOVE 08.10.2019
let foldersdata = BDFDB.sortObject(BDFDB.loadAllData(this, "folders"), "position");
let folders = Object.keys(foldersdata).filter(n => n.indexOf("folder") == 0);
if (folders.length) BDFDB.openConfirmModal(this, `Old ServerFolders data detected!\nFound ${folders.length} old custom folders in the ServerFolders.config.json.\nPress the '${BDFDB.LanguageStrings.OKAY}' button to automatically create a native folder for each old folder and to automatically put the servers in them.`, "Convert?", () => {
let oldGuildFolders = Object.assign({}, BDFDB.LibraryModules.FolderStore.guildFolders);
let guildsInFolders = [];
let guildFolders = [];
let guildPositions = [];
let newfoldersdata = {};
for (let folderid in foldersdata) {
let newid = this.generateID("folder");
let olddata = foldersdata[folderid];
let color1 = BDFDB.colorCONVERT(olddata.color1, "INT");
guildFolders.push({
guildIds: olddata.servers,
folderId: newid,
folderName: olddata.folderName,
folderColor: color1 != null && color1 != undefined ? color1 : 7506394
});
guildsInFolders = guildsInFolders.concat(olddata.servers);
newfoldersdata[newid] = Object.assign({}, olddata);
delete newfoldersdata[newid].position;
delete newfoldersdata[newid].folderName;
delete newfoldersdata[newid].folderId;
delete newfoldersdata[newid].servers;
delete newfoldersdata[newid].isOpen;
newfoldersdata[newid].autoRead = newfoldersdata[newid].autounread;
delete newfoldersdata[newid].autounread;
newfoldersdata[newid].useCloseIcon = true;
newfoldersdata[newid].muteFolder = false;
}
for (let i in oldGuildFolders) if (oldGuildFolders[i].folderId || !guildsInFolders.includes(oldGuildFolders[i].guildIds[0])) guildFolders.push(Object.assign({}, oldGuildFolders[i]));
for (let i in guildFolders) for (let guildid of guildFolders[i].guildIds) guildPositions.push(guildid);
BDFDB.LibraryModules.SettingsUtils.updateRemoteSettings({guildPositions, guildFolders});
BDFDB.removeAllData(this, "folders");
BDFDB.saveAllData(newfoldersdata, this, "folders");
});
BDFDB.WebModules.forceAllUpdates(this);
}
else {
console.error(`%c[${this.getName()}]%c`, 'color: #3a71c1; font-weight: 700;', '', 'Fatal Error: Could not load BD functions!');
}
}
stop () {
if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) {
BDFDB.removeEles(this.foldercontent, BDFDB.dotCN.guildswrapper + ".foldercontent");
let modal = document.querySelector(`.${this.name}-modal`);
if (modal) {
BDFDB.removeClass(modal, `${this.name}-modal`);
let modalclose = modal.querySelector(BDFDB.dotCN.modalclose);
if (modalclose) modalclose.click();
}
for (let folderinner of document.querySelectorAll(`${BDFDB.dotCNS.guildfolderwrapper + BDFDB.dotCN.guildfolderexpandendbackground} ~ ${BDFDB.dotCNS.guildouter + BDFDB.dotCN.guildinner}`)) {
folderinner.removeEventListener("mouseenter", folderinner.ServerFoldersTooltipListener);
folderinner.removeEventListener("mousedown", folderinner.ServerFoldersClickListener);
BDFDB.removeEles(folderinner.querySelectorAll(`${BDFDB.dotCN.guildupperbadge}.count`));
}
for (let foldericon of document.querySelectorAll(BDFDB.dotCN.guildfolder)) {
foldericon.style.removeProperty("background-image");
foldericon.parentElement.parentElement.style.removeProperty("-webkit-mask");
}
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object" && BDFDB.getData("forceOpenFolder", this, "settings")) {
let folder = this.getFolderOfGuildId(BDFDB.LibraryModules.LastGuildStore.getGuildId());
if (folder && !BDFDB.LibraryModules.FolderUtils.isFolderExpanded(folder.folderId)) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(folder.folderId);
}
}
// begin of own functions
onGuildContextMenu (instance, menu, returnvalue) {
if (document.querySelector(".BDFDB-modal")) return;
if (instance.props && instance.props.target && instance.props.folderId && instance.props.type == "GUILD_ICON_FOLDER" && !menu.querySelector(`${this.name}-contextMenuItem`)) {
let folderid = instance.props.folderId;
let folder = BDFDB.LibraryModules.FolderStore.getGuildFolderById(folderid);
let data = this.getFolderConfig(folderid);
let muted = data.muteFolder && folder.guildIds.every(guildid => BDFDB.LibraryModules.MutedUtils.isGuildOrCategoryOrChannelMuted(guildid));
if (data.muteFolder != muted) {
data.muteFolder = muted;
BDFDB.saveData(folderid, data, this, "folders");
}
let [children, index] = BDFDB.getContextMenuGroupAndIndex(returnvalue, "GuildFolderMarkReadItem");
const autoreaditem = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuToggleItem, {
label: this.labels.foldercontext_autoreadfolder_text,
className: `BDFDB-contextMenuToggleItem ${this.name}-contextMenuToggleItem ${this.name}-autoread-contextMenuToggleItem`,
active: data.autoRead,
action: state => {
data.autoRead = state;
BDFDB.saveData(folderid, data, this, "folders");
}
});
if (index > -1) children.splice(index + 1, 0, autoreaditem);
else children.push(autoreaditem);
const muteGroup = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItemGroup, {
className: `BDFDB-contextMenuItemGroup ${this.name}-contextMenuItemGroup`,
children: BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuToggleItem, {
label: this.labels.foldercontext_mutefolder_text,
className: `BDFDB-contextMenuToggleItem ${this.name}-contextMenuToggleItem ${this.name}-mutefolder-contextMenuToggleItem`,
active: muted,
action: state => {
data.muteFolder = state;
BDFDB.saveData(folderid, data, this, "folders");
for (let guildid of folder.guildIds) if (BDFDB.LibraryModules.MutedUtils.isGuildOrCategoryOrChannelMuted(guildid) != state) BDFDB.LibraryModules.GuildSettingsUtils.updateNotificationSettings(guildid, {muted:state, suppress_everyone:state});
}
})
});
returnvalue.props.children.splice(returnvalue.props.children.length - 1, 0, muteGroup);
const deleteGroup = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItemGroup, {
className: `BDFDB-contextMenuItemGroup ${this.name}-contextMenuItemGroup`,
children: BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: this.labels.foldercontext_removefolder_text,
className: `BDFDB-contextMenuItem ${this.name}-contextMenuItem ${this.name}-removefolder-contextMenuItem`,
danger: true,
action: e => {
BDFDB.closeContextMenu(BDFDB.getParentEle(BDFDB.dotCN.contextmenu, e.target));
BDFDB.openConfirmModal(this, `Are you sure you want to remove the folder${folder.folderName ? (" '" + folder.folderName + '"') : ""}?`, () => {this.removeFolder(folderid);});
}
})
});
returnvalue.props.children.push(deleteGroup);
}
else if (instance.props && instance.props.target && instance.props.guild && instance.props.type == "GUILD_ICON_BAR" && !menu.querySelector(`${this.name}-contextMenuItem`)) {
let guildid = instance.props.guild.id;
let folders = this.getFolders();
let folder = this.getFolderOfGuildId(guildid);
let addtofolderitems = [], openguilds = BDFDB.LibraryModules.FolderStore.getSortedGuilds().filter(n => !n.folderId).map(n => n.guilds[0]);
for (let i = 0; i < folders.length; i++) addtofolderitems.push(BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: folders[i].folderName || (this.labels.modal_tabheader1_text + " #" + parseInt(i+1)),
className: `BDFDB-contextMenuItem ${this.name}-contextMenuItem ${this.name}-addtofolder-contextMenuItem`,
action: e => {
BDFDB.closeContextMenu(menu);
this.addGuildToFolder(folders[i].folderId, guildid);
}
}));
let [children, index] = BDFDB.getContextMenuGroupAndIndex(returnvalue, ["FluxContainer(MessageDeveloperModeGroup)", "DeveloperModeGroup"]);
const addType = !addtofolderitems.length ? "contextMenuItem" : "contextMenuSubItem";
const itemgroup = BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItemGroup, {
className: `BDFDB-contextMenuItemGroup ${this.name}-contextMenuItemGroup`,
children: [
BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuSubItem, {
label: this.labels.servercontext_serverfolders_text,
className: `BDFDB-contextMenuSubItem ${this.name}-contextMenuSubItem ${this.name}-guild-contextMenuSubItem`,
render: folder ? [
BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: this.labels.serversubmenu_removefromfolder_text,
className: `BDFDB-contextMenuItem ${this.name}-contextMenuItem ${this.name}-removefromfolder-contextMenuItem`,
danger: true,
action: e => {
BDFDB.closeContextMenu(menu);
this.removeGuildFromFolder(folder.folderId, guildid);
}
})
] : [
BDFDB.React.createElement(BDFDB.LibraryComponents.ContextMenuItem, {
label: this.labels.serversubmenu_createfolder_text,
className: `BDFDB-contextMenuItem ${this.name}-contextMenuItem ${this.name}-createfolder-contextMenuItem`,
disabled: !openguilds.length,
action: e => {
BDFDB.closeContextMenu(menu);
this.openFolderCreationMenu(openguilds, guildid);
}
}),
BDFDB.React.createElement(BDFDB.LibraryComponents[addType.charAt(0).toUpperCase() + addType.slice(1)], {
label: this.labels.serversubmenu_addtofolder_text,
className: `BDFDB-${addType} ${this.name}-${addType} ${this.name}-addtofolder-${addType}`,
disabled: !addtofolderitems.length,
render: addtofolderitems
})
]
})
]
});
if (index > -1) children.splice(index, 0, itemgroup);
else children.push(itemgroup);
}
}
processGuilds (instance, wrapper, returnvalue, methodnames) {
if (methodnames.includes("componentWillUnmount")) {
BDFDB.removeEles(this.foldercontent, BDFDB.dotCN.guildswrapper + ".foldercontent");
delete this.foldercontent;
delete this.foldercontentguilds;
}
if (methodnames.includes("componentDidMount")) {
let process = () => {
if (!wrapper.parentElement.querySelector(BDFDB.dotCN.guildswrapper + ".foldercontent")) {
this.foldercontent = BDFDB.htmlToElement(this.folderContentMarkup);
wrapper.parentElement.insertBefore(this.foldercontent, wrapper.nextElementSibling);
this.foldercontentguilds = this.foldercontent.querySelector(BDFDB.dotCN.guildsscroller);
this.toggleFolderContent();
}
};
if (document.querySelector(BDFDB.dotCNS.guildswrapper + BDFDB.dotCN.guildouter + ":not(.copy) " + BDFDB.dotCN.guildiconwrapper)) process();
else setTimeout(process, 5000);
}
}
processGuildFolder (instance, wrapper, returnvalue, methodnames) {
if (!this.foldercontentguilds) return;
let state = this.getState(instance);
let data = this.getFolderConfig(state.folderId);
if (methodnames.includes("componentDidMount")) {
if (data.muteFolder) for (let guildid of instance.props.guildIds) if (!BDFDB.LibraryModules.MutedUtils.isGuildOrCategoryOrChannelMuted(guildid)) BDFDB.LibraryModules.GuildSettingsUtils.updateNotificationSettings(guildid, {muted:true, suppress_everyone:true});
}
if (!BDFDB.equals(state, this.folderStates[instance.props.folderId])) {
if (data.autoRead && (state.unread || state.badge > 0)) {
clearTimeout(this.folderReads[state.folderId]);
this.folderReads[state.folderId] = setTimeout(() => {
BDFDB.markGuildAsRead(instance.props.guildIds);
}, 10000);
}
if (state.expanded) setImmediate(() => {
for (let guildid of instance.props.guildIds) this.updateGuildInFolderContent(state.folderId, guildid);
if (this.clickedFolder == state.folderId && BDFDB.getData("closeOtherFolders", this, "settings")) for (let openFolderId of BDFDB.LibraryModules.FolderUtils.getExpandedFolders()) if (openFolderId != state.folderId) {
BDFDB.removeEles(this.foldercontent.querySelectorAll(`${BDFDB.dotCN.guildouter}[folderid="${openFolderId}"]`));
BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(openFolderId);
}
this.addSeparator(state.folderId);
this.toggleFolderContent();
});
else setTimeout(() => {
BDFDB.removeEles(this.foldercontent.querySelectorAll(`${BDFDB.dotCN.guildouter}[folderid="${state.folderId}"]`));
if (BDFDB.containsClass(this.foldercontentguilds.firstElementChild, "folderseparatorouter")) BDFDB.removeEles(this.foldercontentguilds.firstElementChild);
this.toggleFolderContent();
}, BDFDB.LibraryModules.FolderUtils.getExpandedFolders().size > 0 ? 0 : 300);
this.changeFolder(state.folderId, wrapper);
}
this.folderStates[state.folderId] = state;
}
processGuild (instance, wrapper, returnvalue, methodnames) {
if (!this.foldercontentguilds) return;
if (instance.props && instance.props.guild) {
if (methodnames.includes("componentDidMount")) {
BDFDB.addEventListener(this, wrapper, "click", () => {setImmediate(() => {
let folder = this.getFolderOfGuildId(instance.props.guild.id);
let folderid = folder ? folder.folderId : null;
let settings = BDFDB.getAllData(this, "settings");
if (settings.closeAllFolders) for (let openFolderId of BDFDB.LibraryModules.FolderUtils.getExpandedFolders()) if (!folderid || openFolderId != folderid || !settings.forceOpenFolder) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(openFolderId);
else if (folderid && settings.closeTheFolder && !settings.forceOpenFolder && BDFDB.LibraryModules.FolderUtils.isFolderExpanded(folderid)) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(folderid);
if (settings.closeAllFolders) for (let openFolderId of BDFDB.LibraryModules.FolderUtils.getExpandedFolders()) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(openFolderId);
else if (settings.closeTheFolder) {
let folder = this.getFolderOfGuildId(instance.props.guild.id);
if (folder && BDFDB.LibraryModules.FolderUtils.isFolderExpanded(folder.folderId)) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(folder.folderId);
}
})});
}
if (methodnames.includes("componentDidUpdate")) {
let folder = this.getFolderOfGuildId(instance.props.guild.id);
if (folder) {
let state = this.getState(instance);
if (!BDFDB.equals(state, this.guildStates[instance.props.guild.id])) this.updateGuildInFolderContent(folder.folderId, instance.props.guild.id);
}
}
}
}
processGuildFolderSettingsModal (instance, wrapper, returnvalue) {
if (instance.props && instance.props.folderId) {
let folderid = instance.props.folderId;
let data = this.getFolderConfig(folderid);
wrapper = wrapper.parentElement;
let root = wrapper.querySelector(BDFDB.dotCN.layermodal);
let header = wrapper.querySelector(BDFDB.dotCN.modalheader);
let form = wrapper.querySelector(BDFDB.dotCN.modalsubinner + " form");
BDFDB.addClass(root, "BDFDB-modal", `${this.name}-modal`, BDFDB.disCN.layermodalmedium);
BDFDB.removeClass(root, BDFDB.disCN.layermodalsmall);
if (header) {
clearInterval(this.settingsModalWait);
header.parentElement.insertBefore(BDFDB.htmlToElement(`
${this.labels.modal_tabheader1_text}
${this.labels.modal_tabheader2_text}
${this.labels.modal_tabheader3_text}
${this.labels.modal_tabheader4_text}
`), header.nextElementSibling);
}
if (root && form) {
form.setAttribute("tab", "folder");
BDFDB.addClass(form, "tab-content", BDFDB.disCN.marginbottom8);
for (let child of form.childNodes) if (form.firstElementChild != child) BDFDB.toggleEles(child, false);
form.appendChild(BDFDB.htmlToElement(`
`));
setIcon(wrapper.querySelector(`.ui-icon-picker-icon[value="${folderIcons[selection] ? selection : -1}"]`), false, true);
BDFDB.addChildEventListener(wrapper, "click", ".ui-icon-picker-icon", e => {
if (BDFDB.containsClass(e.target, BDFDB.disCN.hovercardbutton)) return;
setIcon(wrapper.querySelector(".ui-icon-picker-icon.selected"), false, false);
setIcon(e.currentTarget, true, true);
});
BDFDB.addChildEventListener(wrapper, "click", BDFDB.dotCN.hovercardbutton, e => {
if (BDFDB.containsClass(e.currentTarget.parentElement, "selected")) return;
BDFDB.removeData(e.currentTarget.getAttribute("value"), this, "customicons");
e.currentTarget.parentElement.remove();
BDFDB.showToast(`Custom Icon was deleted.`, {type:"success"});
});
BDFDB.addChildEventListener(wrapper, "mouseenter", ".ui-icon-picker-icon", e => {
setIcon(e.currentTarget, true);
if (e.currentTarget.getAttribute("value") == -1) BDFDB.createTooltip(BDFDB.LanguageStrings.DEFAULT, e.currentTarget, {type:"top"});
});
BDFDB.addChildEventListener(wrapper, "mouseleave", ".ui-icon-picker-icon", e => {
setIcon(e.currentTarget, false);
});
function setIcon (icon, hover, enable) {
if (!icon) return;
let id = icon.getAttribute("value");
if (enable != undefined) BDFDB.toggleClass(icon, "selected", enable);
if (hover) {
if (folderIcons[id]) icon.querySelector(".ui-picker-inner").style.setProperty("background-image", `url(${folderIcons[id].openicon})`);
if (BDFDB.containsClass(icon, "selected")) icon.style.setProperty("background-color", "rgb(255,255,255,0.2)");
else icon.style.setProperty("background-color", "rgb(255,255,255,0.1)");
}
else {
if (folderIcons[id]) icon.querySelector(".ui-picker-inner").style.setProperty("background-image", `url(${folderIcons[id].closedicon})`);
if (BDFDB.containsClass(icon, "selected")) icon.style.setProperty("background-color", "rgb(255,255,255,0.2)");
else icon.style.removeProperty("background-color");
}
}
}
getState (instance) {
let state = {};
for (let key in instance.props) {
if (typeof instance.props[key] != "object" && typeof instance.props[key] != "function") state[key] = instance.props[key];
else if (Array.isArray(instance.props[key])) state[key] = instance.props[key].length;
}
return state;
}
getFolders () {
let found = [], folders = Object.assign({}, BDFDB.LibraryModules.FolderStore.guildFolders);
for (let pos in folders) if (folders[pos].folderId) found.push(Object.assign({}, folders[pos]));
return found;
}
getFolderOfGuildId (guildid) {
if (!guildid) return null;
for (let folder of BDFDB.LibraryModules.FolderStore.guildFolders) if (folder.folderId && folder.guildIds.includes(guildid)) return folder;
}
getFolderConfig (folderid) {
let folder = BDFDB.LibraryModules.FolderStore.getGuildFolderById(folderid) || {};
let config = BDFDB.loadData(folderid, this, "folders") || {
iconID: "-1",
icons: {openicon: null, closedicon: null},
muteFolder: false,
autoRead: false,
copyTooltipColor: false,
useCloseIcon: true,
color1: null,
color2: ["255","255","255"],
color3: null,
color4: null
};
if (!config.color1) config.color1 = BDFDB.colorCONVERT(folder.folderColor, "RGBCOMP") || ["0","0","0"];
return config;
}
toggleFolderContent (forceOpenClose) {
if (!this.foldercontentguilds) return;
forceOpenClose = forceOpenClose === undefined ? BDFDB.LibraryModules.FolderUtils.getExpandedFolders().size > 0 : forceOpenClose;
BDFDB.toggleClass(this.foldercontent, "foldercontentopen", forceOpenClose);
BDFDB.toggleClass(this.foldercontent, "foldercontentclosed", !forceOpenClose);
BDFDB.toggleClass(document.body, "foldercontentopened", forceOpenClose);
}
changeFolder (folderid, wrapper) {
wrapper = wrapper || BDFDB.getFolderDiv(folderid);
if (wrapper) {
let folderinner = wrapper.querySelector(`${BDFDB.dotCN.guildfolderexpandendbackground} ~ ${BDFDB.dotCNS.guildouter + BDFDB.dotCN.guildinner}`);
let foldericon = wrapper.querySelector(BDFDB.dotCN.guildfolder);
if (folderinner && foldericon) {
let folder = BDFDB.LibraryModules.FolderStore.getGuildFolderById(folderid);
let data = this.getFolderConfig(folderid);
BDFDB.removeEles(folderinner.querySelectorAll(`${BDFDB.dotCN.guildupperbadge}.count`));
foldericon.parentElement.parentElement.style.removeProperty("-webkit-mask");
if (BDFDB.getData("showCountBadge", this, "settings")) {
folderinner.appendChild(BDFDB.htmlToElement(`
${folder.guildIds.length}
`));
let width = folder.guildIds.length > 99 ? 36 : (folder.guildIds.length > 9 ? 30 : 24);
foldericon.parentElement.parentElement.style.setProperty("-webkit-mask", `url(data:image/svg+xml;base64,${btoa(``)})`);
}
let icontype = BDFDB.LibraryModules.FolderUtils.isFolderExpanded(folderid) ? "openicon" : "closedicon";
let icon = icontype != "closedicon" || data.useCloseIcon ? data.icons[icontype] : null;
if (icon) foldericon.style.setProperty("background-image", `url(${icon})`, "important");
else foldericon.style.removeProperty("background-image");
folderinner.removeEventListener("mouseenter", folderinner.ServerFoldersTooltipListener);
folderinner.removeEventListener("mousedown", folderinner.ServerFoldersClickListener);
if (data.color3 || data.color4) {
var isgradient3 = data.color3 && BDFDB.isObject(data.color3);
var isgradient4 = data.color4 && BDFDB.isObject(data.color4);
var bgColor = data.color3 ? (!isgradient3 ? BDFDB.colorCONVERT(data.color3, "RGBA") : BDFDB.colorGRADIENT(data.color3)) : "";
var fontColor = data.color4 ? (!isgradient4 ? BDFDB.colorCONVERT(data.color4, "RGBA") : BDFDB.colorGRADIENT(data.color4)) : "";
var folderName = folder.folderName || BDFDB.getReactValue(wrapper, "return.stateNode.props.defaultFolderName");
folderinner.ServerFoldersTooltipListener = () => {
BDFDB.createTooltip(isgradient4 ? `${BDFDB.encodeToHTML(folderName)}` : folderName, folderinner, {type:"right", selector:"ServerFolders-tooltip", style:`${isgradient4 ? '' : 'color: ' + fontColor + ' !important; '}background: ${bgColor} !important; border-color: ${isgradient3 ? BDFDB.colorCONVERT(data.color3[0], "RGBA") : bgColor} !important;`,css:`body ${BDFDB.dotCN.tooltip}:not(.ServerFolders-tooltip) {display: none !important;}`, html:isgradient3});
};
folderinner.addEventListener("mouseenter", folderinner.ServerFoldersTooltipListener);
}
folderinner.ServerFoldersClickListener = () => {
clearTimeout(this.clickedFolderTimeout);
this.clickedFolder = folderid;
this.clickedFolderTimeout = setTimeout(() => {
delete this.clickedFolderTimeout;
}, 3000);
};
folderinner.addEventListener("mousedown", folderinner.ServerFoldersClickListener);
}
}
}
updateGuildInFolderContent (folderid, guildid) {
if (!this.foldercontentguilds || !folderid || !guildid) return;
let guild = BDFDB.LibraryModules.GuildStore.getGuild(guildid);
if (guild) {
let oldCopy = this.foldercontentguilds.querySelector(`.copy[guildid="${guildid}"]`);
let newCopy = this.createCopyOfServer(folderid, guildid);
if (!newCopy) return;
else if (oldCopy) {
this.foldercontentguilds.insertBefore(newCopy, oldCopy);
BDFDB.removeEles(oldCopy);
}
else {
let folder = BDFDB.LibraryModules.FolderStore.getGuildFolderById(folderid);
let position = folder.guildIds.indexOf(guildid);
let siblingId = position > -1 ? folder.guildIds[folder.guildIds.indexOf(guildid) + 1] : null;
let insertNode = siblingId ? this.foldercontentguilds.querySelector(`[guildid="${siblingId}"][folderid="${folderid}"]`) : null;
if (!insertNode) {
let sameFolderEles = this.foldercontentguilds.querySelectorAll(`[folderid="${folderid}"]`);
insertNode = sameFolderEles.length > 0 ? sameFolderEles[sameFolderEles.length - 1].nextSibling : null;
}
this.foldercontentguilds.insertBefore(newCopy, insertNode);
}
if (BDFDB.containsClass(this.foldercontentguilds.firstElementChild, "folderseparatorouter")) BDFDB.removeEles(this.foldercontentguilds.firstElementChild);
}
}
addSeparator (folderid) {
if (!this.foldercontentguilds) return;
if (!this.foldercontent.querySelector(`.folderseparatorouter[folderid="${folderid}"]`) && BDFDB.getData("addSeparators", this, "settings")) this.foldercontentguilds.insertBefore(BDFDB.htmlToElement(`
`), this.foldercontentguilds.querySelectorAll(`[folderid="${folderid}"]`)[0]);
if (BDFDB.containsClass(this.foldercontentguilds.firstElementChild, "folderseparatorouter")) BDFDB.removeEles(this.foldercontentguilds.firstElementChild);
}
createBase64SVG (paths, color1 = "#000000", color2 = "#FFFFFF") {
if (paths.indexOf("`;
if (isgradient1) {
svg += ``;
for (let pos of Object.keys(color1).sort()) svg += ``;
svg += ``;
}
if (isgradient2) {
svg += ``;
for (let pos of Object.keys(color2).sort()) svg += ``;
svg += ``;
}
svg += `${paths.replace("REPLACE_FILL1", isgradient1 ? "url(#grad1)" : BDFDB.colorCONVERT(color1, "RGBA")).replace("REPLACE_FILL2", isgradient2 ? "url(#grad2)" : BDFDB.colorCONVERT(color2, "RGBA"))}`;
return `data:image/svg+xml;base64,${btoa(svg)}`;
}
createCopyOfServer (folderid, guildid) {
if (!folderid || !guildid) return;
let guild = BDFDB.LibraryModules.GuildStore.getGuild(guildid);
let guilddiv = BDFDB.getServerDiv(guildid);
let props = BDFDB.getReactValue(guilddiv, "return.stateNode.props");
if (!guild || !guilddiv || !props) return;
let guildcopy = guilddiv.cloneNode(true);
let guildcopyinner = guildcopy.querySelector(BDFDB.dotCN.guildcontainer);
let guildiconwrapper = guildcopy.querySelector(BDFDB.dotCN.guildiconwrapper);
let guildicon = guildcopy.querySelector(BDFDB.dotCN.guildicon);
let guildpillitem = guildcopy.querySelector(BDFDB.dotCN.guildpillitem);
if (!guildpillitem) {
guildpillitem = BDFDB.htmlToElement(`
`);
guildcopy.insertBefore(guildpillitem, guildcopy.firstElementChild);
guildpillitem = guildpillitem.firstElementChild;
}
guildcopy.setAttribute("guildid", guildid);
guildcopy.setAttribute("folderid", folderid);
guildiconwrapper.style.setProperty("border-radius", props.selected ? "30%" : "50%");
guildiconwrapper.style.setProperty("overflow", "hidden");
guildpillitem.style.setProperty("opacity", props.selected ? 1 : (props.unread ? 0.7 : 0));
guildpillitem.style.setProperty("height", props.selected ? "40px" : "8px");
guildpillitem.style.setProperty("transform", "translate3d(0px, 0px, 0px)");
guildcopy.querySelector("mask").setAttribute("id", "SERVERFOLDERSCOPY" + guildid);
guildcopy.querySelector("mask path").setAttribute("d", "M0 0 l50 0l0 50l-50 0l0 -50Z");
guildcopy.querySelector("foreignObject").setAttribute("mask", "url(#SERVERFOLDERSCOPY" + guildid + ")");
BDFDB.addClass(guildcopy, "copy");
BDFDB.toggleEles(guildcopy, true);
let pillvisible = guildpillitem && guildpillitem.style.getPropertyValue("opacity") != 0;
let borderRadius = new BDFDB.LibraryModules.AnimationUtils.Value(0);
borderRadius
.interpolate({
inputRange: [0, 1],
outputRange: [50, 30]
})
.addListener((value) => {
guildiconwrapper.style.setProperty("border-radius", `${value.value}%`);
});
let pillHeight = new BDFDB.LibraryModules.AnimationUtils.Value(0);
pillHeight
.interpolate({
inputRange: [0, 1],
outputRange: [8, 20]
})
.addListener((value) => {
if (guildpillitem) guildpillitem.style.setProperty("height", `${value.value}px`);
});
let pillOpacity = new BDFDB.LibraryModules.AnimationUtils.Value(0);
pillOpacity
.interpolate({
inputRange: [0, 1],
outputRange: [0, 0.7]
})
.addListener((value) => {
if (guildpillitem) guildpillitem.style.setProperty("opacity", `${value.value}`);
});
let animate = (v) => {
BDFDB.LibraryModules.AnimationUtils.parallel([
BDFDB.LibraryModules.AnimationUtils.timing(borderRadius, {toValue: v, duration: 200}),
BDFDB.LibraryModules.AnimationUtils.spring(pillHeight, {toValue: v, friction: 5})
]).start();
};
let animate2 = (v) => {
BDFDB.LibraryModules.AnimationUtils.parallel([
BDFDB.LibraryModules.AnimationUtils.timing(pillOpacity, {toValue: v, duration: 200}),
]).start();
};
guildcopyinner.addEventListener("mouseenter", () => {
let EditServers = BDFDB.getPlugin("EditServers");
let ESdata = EditServers ? EditServers.getGuildData(guildid, guildcopyinner) : null;
if (ESdata && (ESdata.name || ESdata.color3 || ESdata.color4)) EditServers.changeTooltip(guild, guildcopyinner, "right");
else {
let folderData = BDFDB.loadData(folderid, this, "folders") || {};
let color3 = folderData.copyTooltipColor ? folderData.color3 : null;
let color4 = folderData.copyTooltipColor ? folderData.color4 : null;
let isgradient3 = color3 && BDFDB.isObject(color3);
let isgradient4 = color4 && BDFDB.isObject(color4);
let bgColor = color3 ? (!isgradient3 ? BDFDB.colorCONVERT(color3, "RGBA") : BDFDB.colorGRADIENT(color3)) : "";
let fontColor = color4 ? (!isgradient4 ? BDFDB.colorCONVERT(color4, "RGBA") : BDFDB.colorGRADIENT(color4)) : "";
BDFDB.createTooltip(isgradient4 ? `${BDFDB.encodeToHTML(guild.name)}` : guild.name, guildcopyinner, {type:"right", selector:"guild-folder-tooltip", style:`${isgradient4 ? '' : 'color: ' + fontColor + ' !important; '}background: ${bgColor} !important; border-color: ${isgradient3 ? BDFDB.colorCONVERT(color3[0], "RGBA") : bgColor} !important;`, html:isgradient3});
}
if (guildicon && guildicon.src && guild.icon && guild.icon.startsWith("a_") && guild.features.has("ANIMATED_ICON") && guildicon.src.includes("discordapp.com/icons/")) {
guildicon.src = guildicon.src.replace(".webp", ".gif");
}
pillvisible = guildpillitem && guildpillitem.style.getPropertyValue("opacity") != 0;
if (BDFDB.LibraryModules.LastGuildStore.getGuildId() != guildid) {
animate(1);
if (!pillvisible) animate2(1);
}
});
guildcopyinner.addEventListener("mouseleave", () => {
if (guildicon && guildicon.src && guild.icon && guild.icon.startsWith("a_") && guild.features.has("ANIMATED_ICON") && guildicon.src.includes("discordapp.com/icons/") && !BDFDB.getReactValue(BDFDB.getPlugin("AutoPlayGifs", true), "settings.guildList")) {
guildicon.src = guildicon.src.replace(".gif", ".webp");
}
if (BDFDB.LibraryModules.LastGuildStore.getGuildId() != guildid) {
animate(0);
if (!pillvisible) animate2(0);
}
});
guildcopy.addEventListener("click", e => {
BDFDB.stopEvent(e);
if (BDFDB.pressedKeys.includes(46)) this.removeGuildFromFolder(folderid, guildid);
else {
BDFDB.LibraryModules.GuildUtils.transitionToGuildSync(guild.id);
let settings = BDFDB.getAllData(this, "settings");
if (settings.closeAllFolders) for (let openFolderId of BDFDB.LibraryModules.FolderUtils.getExpandedFolders()) if (openFolderId != folderid || !settings.forceOpenFolder) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(openFolderId);
else if (settings.closeTheFolder && !settings.forceOpenFolder && BDFDB.LibraryModules.FolderUtils.isFolderExpanded(folderid)) BDFDB.LibraryModules.GuildUtils.toggleGuildFolderExpand(folderid);
}
});
guildcopy.addEventListener("contextmenu", e => {
BDFDB.openGuildContextMenu(guilddiv, e);
});
guildcopy.addEventListener("mousedown", e => {
let x = e.pageX, y = e.pageY;
let mousemove = e2 => {
if (Math.sqrt((x - e2.pageX)**2) > 20 || Math.sqrt((y - e2.pageY)**2) > 20) {
document.removeEventListener("mousemove", mousemove);
document.removeEventListener("mouseup", mouseup);
let hovcopy = null;
let placeholder = BDFDB.htmlToElement(this.dragPlaceholderMarkup);
let dragpreview = this.createDragPreview(guilddiv, e);
let dragging = e3 => {
BDFDB.removeEles(placeholder);
BDFDB.toggleEles(guildcopy, false);
this.updateDragPreview(dragpreview, e3);
if (this.foldercontent.contains(e3.target)) {
hovcopy = BDFDB.getParentEle(BDFDB.dotCN.guildouter, e3.target);
if (hovcopy && hovcopy.getAttribute("folderid") == folderid) this.foldercontentguilds.insertBefore(placeholder, hovcopy.nextSibling);
else hovcopy = null;
}
};
let releasing = e3 => {
document.removeEventListener("mousemove", dragging);
document.removeEventListener("mouseup", releasing);
BDFDB.removeEles(placeholder, dragpreview);
BDFDB.toggleEles(guildcopy, true);
let dropfolderdiv = BDFDB.getParentEle(BDFDB.dotCN.guildfolderwrapper, e3.target);
let newfolderid = dropfolderdiv ? BDFDB.getFolderID(dropfolderdiv) : null;
if (newfolderid) {
if (newfolderid != folderid) {
BDFDB.removeEles(guildcopy);
this.addGuildToFolder(newfolderid, guildid);
}
}
else if (hovcopy) {
this.foldercontentguilds.insertBefore(guildcopy, hovcopy.nextSibling);
this.updateGuildPositions(folderid);
}
};
document.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", releasing);
}
};
let mouseup = () => {
document.removeEventListener("mousemove", mousemove);
document.removeEventListener("mouseup", mouseup);
};
document.addEventListener("mousemove", mousemove);
document.addEventListener("mouseup", mouseup);
});
guildcopy.querySelector("a").setAttribute("draggable", false);
return guildcopy;
}
updateGuildPositions (folderid) {
let oldGuildFolders = Object.assign({}, BDFDB.LibraryModules.FolderStore.guildFolders);
let guildFolders = [], guildPositions = [];
for (let i in oldGuildFolders) {
if (oldGuildFolders[i].folderId) {
let newFolder = Object.assign({}, oldGuildFolders[i]);
if (oldGuildFolders[i].folderId == folderid) {
let sameFolderGuilds = this.foldercontentguilds.querySelectorAll(`[guildid][folderid="${folderid}"]`);
if (sameFolderGuilds.length > 0) {
newFolder.guildIds = [];
for (let guilddiv of sameFolderGuilds) newFolder.guildIds.push(guilddiv.getAttribute("guildid"));
}
}
guildFolders.push(newFolder);
}
else guildFolders.push(oldGuildFolders[i]);
}
for (let i in guildFolders) for (let guildid of guildFolders[i].guildIds) guildPositions.push(guildid);
BDFDB.LibraryModules.SettingsUtils.updateRemoteSettings({guildPositions, guildFolders});
}
openFolderCreationMenu (guilds, initguildid) {
let modal = BDFDB.htmlToElement(`
${this.labels.serversubmenu_createfolder_text}
`);
let targetedguildsids = {};
let container = modal.querySelector(".entries");
BDFDB.addChildEventListener(modal, "click", ".btn-done", () => {
let ids = [];
for (let id in targetedguildsids) if (targetedguildsids[id]) ids.push(id);
this.createFolder(ids);
});
for (let guild of guilds) {
if (container.firstElementChild) container.appendChild(BDFDB.htmlToElement(``));
let entry = BDFDB.htmlToElement(`