From 9ce923d4d7b598c955d774bf0c953661496eb278 Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Fri, 27 Oct 2023 19:56:11 -0300
Subject: [PATCH] Fix BetterFolders
---
src/plugins/betterFolders/FolderSideBar.tsx | 64 ++----
src/plugins/betterFolders/betterFolders.css | 17 --
src/plugins/betterFolders/index.ts | 177 ---------------
src/plugins/betterFolders/index.tsx | 229 ++++++++++++++++++++
4 files changed, 251 insertions(+), 236 deletions(-)
delete mode 100644 src/plugins/betterFolders/betterFolders.css
delete mode 100644 src/plugins/betterFolders/index.ts
create mode 100644 src/plugins/betterFolders/index.tsx
diff --git a/src/plugins/betterFolders/FolderSideBar.tsx b/src/plugins/betterFolders/FolderSideBar.tsx
index 6353a9716..f3884701a 100644
--- a/src/plugins/betterFolders/FolderSideBar.tsx
+++ b/src/plugins/betterFolders/FolderSideBar.tsx
@@ -16,56 +16,34 @@
* along with this program. If not, see .
*/
-import { Settings } from "@api/Settings";
-import { classNameFactory } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
-import { findByPropsLazy, findStoreLazy } from "@webpack";
-import { i18n, React, useStateFromStores } from "@webpack/common";
+import { LazyComponent } from "@utils/react";
+import { find, findByPropsLazy } from "@webpack";
+import { React, useStateFromStores } from "@webpack/common";
-const cl = classNameFactory("vc-bf-");
-const classes = findByPropsLazy("sidebar", "guilds");
+import { ExpandedGuildFolderStore, settings } from ".";
const Animations = findByPropsLazy("a", "animated", "useTransition");
-const ChannelRTCStore = findStoreLazy("ChannelRTCStore");
-const ExpandedGuildFolderStore = findStoreLazy("ExpandedGuildFolderStore");
+const GuildsBar = LazyComponent(() => find(m => m.type?.toString().includes('("guildsnav")')));
-function Guilds(props: {
- className: string;
- bfGuildFolders: any[];
-}) {
- // @ts-expect-error
- const res = Vencord.Plugins.plugins.BetterFolders.Guilds(props);
-
- // TODO: Make this better
- const scrollerProps = res.props.children?.props?.children?.props?.children?.[1]?.props;
- if (scrollerProps?.children) {
- const servers = scrollerProps.children.find(c => c?.props?.["aria-label"] === i18n.Messages.SERVERS);
- if (servers) scrollerProps.children = servers;
- }
-
- return res;
-}
-
-export default ErrorBoundary.wrap(() => {
+export default ErrorBoundary.wrap(guildsBarProps => {
const expandedFolders = useStateFromStores([ExpandedGuildFolderStore], () => ExpandedGuildFolderStore.getExpandedFolders());
- const fullscreen = useStateFromStores([ChannelRTCStore], () => ChannelRTCStore.isFullscreenInContext());
-
- const guilds = document.querySelector(`.${classes.guilds}`);
-
- const visible = !!expandedFolders.size;
- const className = cl("folder-sidebar", { fullscreen });
const Sidebar = (
-
);
- if (!guilds || !Settings.plugins.BetterFolders.sidebarAnim)
+ const visible = !!expandedFolders.size;
+ const guilds = document.querySelector(guildsBarProps.className.split(" ").map(c => `.${c}`).join(""));
+
+ if (!guilds || !settings.store.sidebarAnim) {
return visible
- ?
{Sidebar}
+ ? {Sidebar}
: null;
+ }
return (
{
leave={{ width: 0 }}
config={{ duration: 200 }}
>
- {(style, show) => show && (
-
- {Sidebar}
-
- )}
+ {(style, show) =>
+ show && (
+
+ {Sidebar}
+
+ )
+ }
);
}, { noop: true });
diff --git a/src/plugins/betterFolders/betterFolders.css b/src/plugins/betterFolders/betterFolders.css
deleted file mode 100644
index 5d8fc2188..000000000
--- a/src/plugins/betterFolders/betterFolders.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.vc-bf-folder-sidebar [class*="wrapper-"] > [class*="listItem-"]:first-of-type,
-.vc-bf-folder-sidebar [class*="unreadMentionsIndicator"] {
- display: none;
-}
-
-.vc-bf-folder-sidebar [class*="expandedFolderBackground-"] {
- background-color: transparent;
-}
-
-.vc-bf-folder-sidebar {
- display: flex;
-}
-
-.vc-bf-fullscreen {
- width: 0 !important;
- visibility: hidden;
-}
diff --git a/src/plugins/betterFolders/index.ts b/src/plugins/betterFolders/index.ts
deleted file mode 100644
index d41ba75c7..000000000
--- a/src/plugins/betterFolders/index.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Vencord, a modification for Discord's desktop app
- * Copyright (c) 2023 Vendicated and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-
-import "./betterFolders.css";
-
-import { definePluginSettings } from "@api/Settings";
-import { Devs } from "@utils/constants";
-import definePlugin, { OptionType } from "@utils/types";
-import { findByPropsLazy, findLazy, findStoreLazy } from "@webpack";
-import { FluxDispatcher } from "@webpack/common";
-
-import FolderSideBar from "./FolderSideBar";
-
-const GuildsTree = findLazy(m => m.prototype?.convertToFolder);
-const GuildFolderStore = findStoreLazy("SortedGuildStore");
-const ExpandedFolderStore = findStoreLazy("ExpandedGuildFolderStore");
-const FolderUtils = findByPropsLazy("move", "toggleGuildFolderExpand");
-
-const settings = definePluginSettings({
- sidebar: {
- type: OptionType.BOOLEAN,
- description: "Display servers from folder on dedicated sidebar",
- default: true,
- },
- sidebarAnim: {
- type: OptionType.BOOLEAN,
- description: "Animate opening the folder sidebar",
- default: true,
- },
- closeAllFolders: {
- type: OptionType.BOOLEAN,
- description: "Close all folders when selecting a server not in a folder",
- default: false,
- },
- closeAllHomeButton: {
- type: OptionType.BOOLEAN,
- description: "Close all folders when clicking on the home button",
- default: false,
- },
- closeOthers: {
- type: OptionType.BOOLEAN,
- description: "Close other folders when opening a folder",
- default: false,
- },
- forceOpen: {
- type: OptionType.BOOLEAN,
- description: "Force a folder to open when switching to a server of that folder",
- default: false,
- },
-});
-
-export default definePlugin({
- name: "BetterFolders",
- description: "Shows server folders on dedicated sidebar and adds folder related improvements",
- authors: [Devs.juby, Devs.AutumnVN],
- patches: [
- {
- find: '("guildsnav")',
- predicate: () => settings.store.sidebar,
- replacement: [
- {
- match: /(\i)\(\){return \i\(\(0,\i\.jsx\)\("div",{className:\i\(\)\.guildSeparator}\)\)}/,
- replace: "$&$self.Separator=$1;"
- },
-
- // Folder component patch
- {
- match: /\i\(\(function\(\i,\i,\i\){var \i=\i\.key;return.+\(\i\)},\i\)}\)\)/,
- replace: "arguments[0].bfHideServers?null:$&"
- },
-
- // BEGIN Guilds component patch
- {
- match: /(\i)\.themeOverride,(.{15,25}\(function\(\){var \i=)(\i\.\i\.getGuildsTree\(\))/,
- replace: "$1.themeOverride,bfPatch=$1.bfGuildFolders,$2bfPatch?$self.getGuildsTree(bfPatch,$3):$3"
- },
- {
- match: /return(\(0,\i\.jsx\))(\(\i,{)(folderNode:\i,setNodeRef:\i\.setNodeRef,draggable:!0,.+},\i\.id\));case/,
- replace: "var bfHideServers=typeof bfPatch==='undefined',folder=$1$2bfHideServers,$3;return !bfHideServers&&arguments[1]?[$1($self.Separator,{}),folder]:folder;case"
- },
- // END
-
- {
- match: /\("guildsnav"\);return\(0,\i\.jsx\)\(.{1,6},{navigator:\i,children:\(0,\i\.jsx\)\(/,
- replace: "$&$self.Guilds="
- }
- ]
- },
- {
- find: "APPLICATION_LIBRARY,render",
- predicate: () => settings.store.sidebar,
- replacement: {
- match: /(\(0,\i\.jsx\))\(\i\..,{className:\i\(\)\.guilds,themeOverride:\i}\)/,
- replace: "$&,$1($self.FolderSideBar,{})"
- }
- },
- {
- find: '("guildsnav")',
- predicate: () => settings.store.closeAllHomeButton,
- replacement: {
- match: ",onClick:function(){if(!__OVERLAY__){",
- replace: "$&$self.closeFolders();"
- }
- }
- ],
-
- settings,
-
- start() {
- const getGuildFolder = (id: string) => GuildFolderStore.getGuildFolders().find(f => f.guildIds.includes(id));
-
- FluxDispatcher.subscribe("CHANNEL_SELECT", this.onSwitch = data => {
- if (!settings.store.closeAllFolders && !settings.store.forceOpen)
- return;
-
- if (this.lastGuildId !== data.guildId) {
- this.lastGuildId = data.guildId;
-
- const guildFolder = getGuildFolder(data.guildId);
- if (guildFolder?.folderId) {
- if (settings.store.forceOpen && !ExpandedFolderStore.isFolderExpanded(guildFolder.folderId))
- FolderUtils.toggleGuildFolderExpand(guildFolder.folderId);
- } else if (settings.store.closeAllFolders)
- this.closeFolders();
- }
- });
-
- FluxDispatcher.subscribe("TOGGLE_GUILD_FOLDER_EXPAND", this.onToggleFolder = e => {
- if (settings.store.closeOthers && !this.dispatching)
- FluxDispatcher.wait(() => {
- const expandedFolders = ExpandedFolderStore.getExpandedFolders();
- if (expandedFolders.size > 1) {
- this.dispatching = true;
-
- for (const id of expandedFolders) if (id !== e.folderId)
- FolderUtils.toggleGuildFolderExpand(id);
-
- this.dispatching = false;
- }
- });
- });
- },
-
- stop() {
- FluxDispatcher.unsubscribe("CHANNEL_SELECT", this.onSwitch);
- FluxDispatcher.unsubscribe("TOGGLE_GUILD_FOLDER_EXPAND", this.onToggleFolder);
- },
-
- FolderSideBar,
-
- getGuildsTree(folders, oldTree) {
- const tree = new GuildsTree();
- tree.root.children = oldTree.root.children.filter(e => folders.includes(e.id));
- tree.nodes = folders.map(id => oldTree.nodes[id]);
- return tree;
- },
-
- closeFolders() {
- for (const id of ExpandedFolderStore.getExpandedFolders())
- FolderUtils.toggleGuildFolderExpand(id);
- },
-});
diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx
new file mode 100644
index 000000000..e4bdc9800
--- /dev/null
+++ b/src/plugins/betterFolders/index.tsx
@@ -0,0 +1,229 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2023 Vendicated and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+*/
+
+import { definePluginSettings } from "@api/Settings";
+import { Devs } from "@utils/constants";
+import definePlugin, { OptionType } from "@utils/types";
+import { findByPropsLazy, findStoreLazy } from "@webpack";
+import { FluxDispatcher, i18n } from "@webpack/common";
+
+import FolderSideBar from "./FolderSideBar";
+
+const GuildFolderStore = findStoreLazy("SortedGuildStore");
+export const ExpandedGuildFolderStore = findStoreLazy("ExpandedGuildFolderStore");
+const FolderUtils = findByPropsLazy("move", "toggleGuildFolderExpand");
+
+let lastGuildId = null as string | null;
+let dispatchingFoldersClose = false;
+
+function getGuildFolder(id: string) {
+ return GuildFolderStore.getGuildFolders().find(folder => folder.guildIds.includes(id));
+}
+
+function closeFolders() {
+ for (const id of ExpandedGuildFolderStore.getExpandedFolders())
+ FolderUtils.toggleGuildFolderExpand(id);
+}
+
+export const settings = definePluginSettings({
+ sidebar: {
+ type: OptionType.BOOLEAN,
+ description: "Display servers from folder on dedicated sidebar",
+ restartNeeded: true,
+ default: true
+ },
+ sidebarAnim: {
+ type: OptionType.BOOLEAN,
+ description: "Animate opening the folder sidebar",
+ restartNeeded: true,
+ default: true
+ },
+ closeAllFolders: {
+ type: OptionType.BOOLEAN,
+ description: "Close all folders when selecting a server not in a folder",
+ default: false
+ },
+ closeAllHomeButton: {
+ type: OptionType.BOOLEAN,
+ description: "Close all folders when clicking on the home button",
+ restartNeeded: true,
+ default: false
+ },
+ closeOthers: {
+ type: OptionType.BOOLEAN,
+ description: "Close other folders when opening a folder",
+ default: false
+ },
+ forceOpen: {
+ type: OptionType.BOOLEAN,
+ description: "Force a folder to open when switching to a server of that folder",
+ default: false
+ }
+});
+
+export default definePlugin({
+ name: "BetterFolders",
+ description: "Shows server folders on dedicated sidebar and adds folder related improvements",
+ authors: [Devs.juby, Devs.AutumnVN, Devs.Nuckyz],
+
+ settings,
+
+ patches: [
+ {
+ find: '("guildsnav")',
+ predicate: () => settings.store.sidebar,
+ replacement: [
+ // Create the isBetterFolders variable in the GuildsBar component
+ {
+ match: /(?<=let{disableAppDownload:\i=\i\.isPlatformEmbedded,isOverlay:.+?)(?=}=\i,)/,
+ replace: ",isBetterFolders"
+ },
+ // If we are rendering the Better Folders sidebar, we filter out everything but the servers and folders from the GuildsBar Guild List children
+ {
+ match: /lastTargetNode:\i\[\i\.length-1\].+?Fragment.+?\]}\)\]/,
+ replace: '$&.filter($self.makeGuildsBarGuildListFilter(typeof isBetterFolders!=="undefined"?isBetterFolders:false))'
+ },
+ // If we are rendering the Better Folders sidebar, we filter out everything but the scroller for the guild list from the GuildsBar Tree children
+ {
+ match: /unreadMentionsIndicatorBottom,barClassName.+?}\)\]/,
+ replace: '$&.filter($self.makeGuildsBarTreeFilter(typeof isBetterFolders!=="undefined"?isBetterFolders:false))'
+ },
+ // Export the isBetterFolders variable to the folders component
+ {
+ match: /(?<=\.Messages\.SERVERS.+?switch\((\i)\.type\){case \i\.\i\.FOLDER:.+?folderNode:\i,)/,
+ replace: 'isBetterFolders:typeof isBetterFolders!=="undefined"?isBetterFolders:false,'
+ },
+ // Avoid rendering servers that are not in folders in the Better Folders sidebar
+ {
+ match: /(?<=\.Messages\.SERVERS.+?switch\((\i)\.type\){case \i\.\i\.FOLDER:.+?GUILD:)/,
+ replace: 'if((typeof isBetterFolders!=="undefined"?isBetterFolders:false)&&$1.parentId==null)return null;'
+ }
+ ]
+ },
+ {
+ find: ".FOLDER_ITEM_GUILD_ICON_MARGIN);",
+ replacement: [
+ // Create the isBetterFolders variable in the nested folders component (the parent exports all the props so we don't have to patch it)
+ {
+ match: /(?<=let{folderNode:\i,setNodeRef:\i,)/,
+ replace: "isBetterFolders,"
+ },
+ // If we are rendering the normal GuildsBar sidebar, we make Discord think the folder is always collapsed to show better icons (the mini guild icons) and avoid transitions
+ {
+ match: /(?<=let{folderNode:\i,setNodeRef:\i,.+?expanded:(\i).+?;)(?=let)/,
+ replace: '$1=(typeof isBetterFolders!=="undefined"?isBetterFolders:false)?$1:false;'
+ },
+ // If we are rendering the Better Folders sidebar, we filter out folders that are not expanded
+ {
+ match: /(?=return\(0,\i.\i\)\("div")(?<=selected:\i,expanded:(\i),.+?)/,
+ replace: (_, expanded) => `if((typeof isBetterFolders!=="undefined"?isBetterFolders:false)&&!${expanded})return null;`
+ }
+ // This code is required for the plugin to work, but we don't need it right now because we are making Discord think the folder is always collapsed
+ // If we no longer want to make Discord think the folder is always collapsed, we can use this code for the plugin to work
+ // One reason to no longer want that is to make better icons (the mini guild icons) no longer show
+ /* // Disable expanding and collapsing folders transition in the normal GuildsBar sidebar
+ {
+ match: /(?<=\.Messages\.SERVER_FOLDER_PLACEHOLDER.+?useTransition\)\()/,
+ replace: '(typeof isBetterFolders!=="undefined"?isBetterFolders:false)&&'
+ },
+ // If we are rendering the normal GuildsBar sidebar, we avoid rendering guilds from folders that are expanded
+ {
+ match: /expandedFolderBackground,.+?,(?=\i\(\(\i,\i,\i\)=>{let{key.{0,45}ul)(?<=selected:\i,expanded:(\i),.+?)/,
+ replace: (m, expanded) => `${m}((typeof isBetterFolders!=="undefined"?isBetterFolders:false)||!${expanded})&&`
+ } */
+ ]
+ },
+ {
+ find: "APPLICATION_LIBRARY,render",
+ predicate: () => settings.store.sidebar,
+ replacement: {
+ // Render the Better Folders sidebar
+ match: /(?<=({className:\i\.guilds,themeOverride:\i})\))/,
+ replace: ",$self.FolderSideBar($1)"
+ }
+ },
+ {
+ find: ".Messages.DISCODO_DISABLED",
+ predicate: () => settings.store.closeAllHomeButton,
+ replacement: {
+ // Close all folders when clicking the home button
+ match: /(?<=onClick:\(\)=>{)(?=.{0,200}"discodo")/,
+ replace: "$self.closeFolders();"
+ }
+ }
+ ],
+
+ flux: {
+ CHANNEL_SELECT(data) {
+ if (!settings.store.closeAllFolders && !settings.store.forceOpen)
+ return;
+
+ if (lastGuildId !== data.guildId) {
+ lastGuildId = data.guildId;
+ const guildFolder = getGuildFolder(data.guildId);
+
+ if (guildFolder?.folderId) {
+ if (settings.store.forceOpen && !ExpandedGuildFolderStore.isFolderExpanded(guildFolder.folderId)) {
+ FolderUtils.toggleGuildFolderExpand(guildFolder.folderId);
+ }
+ } else if (settings.store.closeAllFolders) {
+ closeFolders();
+ }
+ }
+ },
+
+ TOGGLE_GUILD_FOLDER_EXPAND(data) {
+ if (settings.store.closeOthers && !dispatchingFoldersClose) {
+ dispatchingFoldersClose = true;
+
+ FluxDispatcher.wait(() => {
+ const expandedFolders = ExpandedGuildFolderStore.getExpandedFolders();
+
+ if (expandedFolders.size > 1) {
+ for (const id of expandedFolders) if (id !== data.folderId)
+ FolderUtils.toggleGuildFolderExpand(id);
+ }
+
+ dispatchingFoldersClose = false;
+ });
+ }
+ }
+ },
+
+ makeGuildsBarGuildListFilter(isBetterFolders: boolean) {
+ return child => {
+ if (isBetterFolders) {
+ return child?.props?.["aria-label"] === i18n.Messages.SERVERS;
+ }
+ return true;
+ };
+ },
+
+ makeGuildsBarTreeFilter(isBetterFolders: boolean) {
+ return child => {
+ if (isBetterFolders) {
+ return "onScroll" in child.props;
+ }
+ return true;
+ };
+ },
+
+ FolderSideBar: guildsBarProps => ,
+
+ closeFolders
+});