diff --git a/src/plugins/showHiddenChannels.tsx b/src/plugins/showHiddenChannels.tsx
new file mode 100644
index 000000000..9415900a4
--- /dev/null
+++ b/src/plugins/showHiddenChannels.tsx
@@ -0,0 +1,137 @@
+/*
+ * Vencord, a modification for Discord's desktop app
+ * Copyright (c) 2022 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 { Flex } from "../components/Flex";
+import { ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "../utils/modal";
+import definePlugin, { OptionType } from "../utils/types";
+import { Settings } from "../Vencord";
+import { waitFor } from "../webpack";
+import { Button, ChannelStore, Text } from "../webpack/common";
+
+const VIEW_CHANNEL = 1024n;
+
+let can = (permission, channel) => true;
+waitFor(m => m.can && m.initialize, m => ({ can } = m));
+
+export default definePlugin({
+ name: "ShowHiddenChannels",
+ description: "Show hidden channels",
+ authors: [
+ {
+ name: "BigDuck",
+ id: 1024588272623681609n
+ },
+ {
+ name: "Average React Enjoyer",
+ id: 1004904120056029256n
+ }
+ ],
+ options: {
+ hideUnreads: {
+ description: "Hide unreads",
+ type: OptionType.BOOLEAN,
+ default: true,
+ restartNeeded: true // Restart is needed to refresh channel list
+ }
+ },
+ patches: [
+ {
+ // RenderLevel defines if a channel is hidden, collapsed in category, visible, etc
+ find: ".CannotShow",
+ replacement: {
+ match: /renderLevel:(\w+)\.CannotShow/g,
+ replace: "renderLevel:$1.Show"
+ }
+ },
+ {
+ // This is where the logic that chooses the icon is, we overide it to be a locked voice channel if it's hidden
+ find: ".rulesChannelId))",
+ replacement: {
+ match: /(\w+)\.locked(.*?)switch\((\w+)\.type\)({case \w+\.\w+\.GUILD_ANNOUNCEMENT)/g,
+ replace: "Vencord.Plugins.plugins.ShowHiddenChannels.isHiddenChannel($3)||$1.locked$2switch($3._isHiddenChannel?2:$3.type)$4"
+ }
+ },
+ {
+ find: "selectChannel:function",
+ replacement: [
+ {
+ match: /selectChannel:function\((\w)\){/g,
+ replace: "selectChannel:function($1){if(Vencord.Plugins.plugins.ShowHiddenChannels.channelSelected($1)) return;"
+ }
+ ]
+ },
+ {
+ find: "?\"button\":\"link\"",
+ predicate: () => Settings.plugins.ShowHiddenChannels.hideUnreads === true,
+ replacement: {
+ match: /(\w)\.connected,(\w)=(\w\.unread),(\w=\w\.canHaveDot)/g,
+ replace: "$1.connected,$2=Vencord.Plugins.plugins.ShowHiddenChannels.isHiddenChannel($1.channel)?false:$3,$4"
+ }
+ }
+ ],
+ isHiddenChannel(channel) {
+ if (!channel) return false;
+ channel._isHiddenChannel = !can(VIEW_CHANNEL, channel);
+ return channel._isHiddenChannel;
+ },
+ channelSelected(channelData) {
+ const channel = ChannelStore.getChannel(channelData.channelId);
+
+ if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return false;
+
+ const isHidden = this.isHiddenChannel(channel);
+ if (isHidden)
+ openModal(modalProps => (
+
+
+
+ {channel.name}
+ {(channel.isNSFW() && (
+
+ NSFW
+
+ ))}
+
+
+
+ You don't have the permission to view the messages in this channel.
+ {(channel.topic || "").length > 0 && (
+ <>
+
+ Topic:
+
+ {channel.topic}
+ >
+ )}
+
+
+
+
+
+
+
+ ));
+ return isHidden;
+ }
+});