2022-10-23 09:44:21 +00:00
|
|
|
/*
|
|
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2023-02-01 11:11:05 +00:00
|
|
|
import "./style.css";
|
2022-10-30 18:17:46 +00:00
|
|
|
|
2023-01-25 02:35:34 +00:00
|
|
|
import { definePluginSettings } from "@api/settings";
|
2023-02-01 11:11:05 +00:00
|
|
|
import ErrorBoundary from "@components/ErrorBoundary";
|
2022-11-28 12:37:55 +00:00
|
|
|
import { Devs } from "@utils/constants";
|
|
|
|
import definePlugin, { OptionType } from "@utils/types";
|
2023-01-25 03:08:37 +00:00
|
|
|
import { findByPropsLazy, findLazy } from "@webpack";
|
2023-02-01 11:11:05 +00:00
|
|
|
import { ChannelStore, PermissionStore, Tooltip } from "@webpack/common";
|
2023-01-25 02:35:34 +00:00
|
|
|
import { Channel } from "discord-types/general";
|
2023-01-23 21:04:50 +00:00
|
|
|
|
2023-02-01 11:11:05 +00:00
|
|
|
import HiddenChannelLockScreen from "./components/HiddenChannelLockScreen";
|
|
|
|
|
2023-01-23 21:04:50 +00:00
|
|
|
const ChannelListClasses = findByPropsLazy("channelName", "subtitle", "modeMuted", "iconContainer");
|
2023-01-25 03:08:37 +00:00
|
|
|
const Permissions = findLazy(m => typeof m.VIEW_CHANNEL === "bigint");
|
2023-01-23 21:04:50 +00:00
|
|
|
|
|
|
|
enum ShowMode {
|
|
|
|
LockIcon,
|
|
|
|
HiddenIconWithMutedStyle
|
|
|
|
}
|
|
|
|
|
2023-01-25 02:35:34 +00:00
|
|
|
const settings = definePluginSettings({
|
|
|
|
hideUnreads: {
|
|
|
|
description: "Hide Unreads",
|
|
|
|
type: OptionType.BOOLEAN,
|
|
|
|
default: true,
|
|
|
|
restartNeeded: true
|
|
|
|
},
|
|
|
|
showMode: {
|
|
|
|
description: "The mode used to display hidden channels.",
|
|
|
|
type: OptionType.SELECT,
|
|
|
|
options: [
|
|
|
|
{ label: "Plain style with Lock Icon instead", value: ShowMode.LockIcon, default: true },
|
|
|
|
{ label: "Muted style with hidden eye icon on the right", value: ShowMode.HiddenIconWithMutedStyle },
|
|
|
|
],
|
|
|
|
restartNeeded: true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-10-23 09:44:21 +00:00
|
|
|
export default definePlugin({
|
|
|
|
name: "ShowHiddenChannels",
|
2023-01-23 21:04:50 +00:00
|
|
|
description: "Show channels that you do not have access to view.",
|
2023-01-28 00:40:10 +00:00
|
|
|
authors: [Devs.BigDuck, Devs.AverageReactEnjoyer, Devs.D3SOX, Devs.Ven, Devs.Nuckyz, Devs.Nickyux, Devs.dzshn],
|
2023-01-25 02:35:34 +00:00
|
|
|
settings,
|
|
|
|
|
2022-10-23 09:44:21 +00:00
|
|
|
patches: [
|
|
|
|
{
|
|
|
|
// RenderLevel defines if a channel is hidden, collapsed in category, visible, etc
|
|
|
|
find: ".CannotShow",
|
2023-01-23 21:04:50 +00:00
|
|
|
// These replacements only change the necessary CannotShow's
|
|
|
|
replacement: [
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=isChannelGatedAndVisible\(this\.record\.guild_id,this\.record\.id\).+?renderLevel:)(?<RenderLevels>\i)\..+?(?=,)/,
|
|
|
|
replace: "this.category.isCollapsed?$<RenderLevels>.WouldShowIfUncollapsed:$<RenderLevels>.Show"
|
2023-01-23 21:04:50 +00:00
|
|
|
},
|
2023-01-25 02:35:34 +00:00
|
|
|
// Move isChannelGatedAndVisible renderLevel logic to the bottom to not show hidden channels in case they are muted
|
2023-01-23 21:04:50 +00:00
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=(?<permissionCheck>if\(!\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL.+?{)if\(this\.id===\i\).+?};)(?<isChannelGatedAndVisibleCondition>if\(!\i\.\i\.isChannelGatedAndVisible\(.+?})(?<restOfFunction>.+?)(?=return{renderLevel:\i\.Show.{1,40}return \i)/,
|
|
|
|
replace: "$<restOfFunction>$<permissionCheck>$<isChannelGatedAndVisibleCondition>}"
|
2023-01-23 21:04:50 +00:00
|
|
|
},
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=renderLevel:(?<renderLevelExpression>\i\(this,\i\)\?\i\.Show:\i\.WouldShowIfUncollapsed).+?renderLevel:).+?(?=,)/,
|
|
|
|
replace: "$<renderLevelExpression>"
|
2023-01-23 21:04:50 +00:00
|
|
|
},
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=activeJoinedRelevantThreads.+?renderLevel:.+?,threadIds:\i\(this.record.+?renderLevel:)(?<RenderLevels>\i)\..+?(?=,)/,
|
|
|
|
replace: "$<RenderLevels>.Show"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
match: /(?<=getRenderLevel=function.+?return ).+?\?(?<renderLevelExpressionWithoutPermCheck>.+?):\i\.CannotShow(?=})/,
|
|
|
|
replace: "$<renderLevelExpressionWithoutPermCheck>"
|
2023-01-23 21:04:50 +00:00
|
|
|
}
|
|
|
|
]
|
2022-10-23 09:44:21 +00:00
|
|
|
},
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
find: "VoiceChannel.renderPopout: There must always be something to render",
|
|
|
|
replacement: [
|
|
|
|
// Do nothing when trying to join a voice channel if the channel is hidden
|
|
|
|
{
|
|
|
|
match: /(?<=handleClick=function\(\){)(?=.{1,80}(?<this>\i)\.handleVoiceConnect\(\))/,
|
|
|
|
replace: "if($self.isHiddenChannel($<this>.props.channel))return;"
|
|
|
|
},
|
|
|
|
// Render null instead of the buttons if the channel is hidden
|
|
|
|
...[
|
|
|
|
"renderEditButton",
|
|
|
|
"renderInviteButton",
|
|
|
|
"renderOpenChatButton"
|
|
|
|
].map(func => ({
|
|
|
|
match: new RegExp(`(?<=\\i\\.${func}=function\\(\\){)`, "g"), // Global because Discord has multiple declarations of the same functions
|
|
|
|
replace: "if($self.isHiddenChannel(this.props.channel))return null;"
|
|
|
|
}))
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
find: ".Messages.CHANNEL_TOOLTIP_DIRECTORY",
|
|
|
|
predicate: () => settings.store.showMode === ShowMode.LockIcon,
|
2022-10-24 21:22:39 +00:00
|
|
|
replacement: {
|
2023-01-25 02:35:34 +00:00
|
|
|
// Lock Icon
|
|
|
|
match: /(?=switch\((?<channel>\i)\.type\).{1,30}\.GUILD_ANNOUNCEMENT.{1,30}\(0,\i\.\i\))/,
|
|
|
|
replace: "if($self.isHiddenChannel($<channel>))return $self.LockIcon;"
|
2022-10-24 21:22:39 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
2023-01-23 21:04:50 +00:00
|
|
|
find: ".UNREAD_HIGHLIGHT",
|
2023-01-25 02:35:34 +00:00
|
|
|
predicate: () => settings.store.hideUnreads === true,
|
2023-01-23 21:04:50 +00:00
|
|
|
replacement: [{
|
|
|
|
// Hide unreads
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=\i\.connected,\i=)(?=(?<props>\i)\.unread)/,
|
|
|
|
replace: "$self.isHiddenChannel($<props>.channel)?false:"
|
2023-01-23 21:04:50 +00:00
|
|
|
}]
|
2022-10-23 09:44:21 +00:00
|
|
|
},
|
2023-01-23 21:04:50 +00:00
|
|
|
{
|
|
|
|
find: ".UNREAD_HIGHLIGHT",
|
2023-01-25 02:35:34 +00:00
|
|
|
predicate: () => settings.store.showMode === ShowMode.HiddenIconWithMutedStyle,
|
2023-01-23 21:04:50 +00:00
|
|
|
replacement: [
|
|
|
|
// Make the channel appear as muted if it's hidden
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=\i\.name,\i=)(?=(?<props>\i)\.muted)/,
|
|
|
|
replace: "$self.isHiddenChannel($<props>.channel)?true:"
|
2023-01-23 21:04:50 +00:00
|
|
|
},
|
|
|
|
// Add the hidden eye icon if the channel is hidden
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=(?<channel>\i)=\i\.channel,.+?\(\)\.children.+?:null)/,
|
|
|
|
replace: ",$self.isHiddenChannel($<channel>)?$self.HiddenChannelIcon():null"
|
2023-01-23 21:04:50 +00:00
|
|
|
},
|
|
|
|
// Make voice channels also appear as muted if they are muted
|
|
|
|
{
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=\i\(\)\.wrapper:\i\(\)\.notInteractive,)(?<otherClasses>.+?)(?<mutedClassExpression>(?<isMuted>\i)\?\i\.MUTED)/,
|
|
|
|
replace: "$<mutedClassExpression>:\"\",$<otherClasses>$<isMuted>?\"\""
|
2023-01-23 21:04:50 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
2023-01-25 02:35:34 +00:00
|
|
|
// Make muted channels also appear as unread if hide unreads is false, using the HiddenIconWithMutedStyle and the channel is hidden
|
|
|
|
{
|
|
|
|
find: ".UNREAD_HIGHLIGHT",
|
|
|
|
predicate: () => settings.store.hideUnreads === false && settings.store.showMode === ShowMode.HiddenIconWithMutedStyle,
|
|
|
|
replacement: {
|
|
|
|
match: /(?<=(?<channel>\i)=\i\.channel,.+?\.LOCKED:\i)/,
|
|
|
|
replace: "&&!($self.settings.store.hideUnreads===false&&$self.isHiddenChannel($<channel>))"
|
|
|
|
}
|
|
|
|
},
|
2022-10-27 18:25:51 +00:00
|
|
|
{
|
|
|
|
// Hide New unreads box for hidden channels
|
|
|
|
find: '.displayName="ChannelListUnreadsStore"',
|
|
|
|
replacement: {
|
2023-01-25 02:35:34 +00:00
|
|
|
match: /(?<=return null!=(?<channel>\i))(?=.{1,130}hasRelevantUnread\(\i\))/,
|
|
|
|
replace: "&&!$self.isHiddenChannel($<channel>)"
|
2022-10-27 18:25:51 +00:00
|
|
|
}
|
2023-01-28 00:40:10 +00:00
|
|
|
},
|
2023-02-01 11:11:05 +00:00
|
|
|
// Only render the channel header and buttons that work when transitioning to a hidden channel
|
|
|
|
{
|
|
|
|
find: "Missing channel in Channel.renderHeaderToolbar",
|
|
|
|
replacement: [
|
|
|
|
{
|
|
|
|
match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_TEXT:)(?=.+?;(?<pushNotificationButtonExpression>.+?{channel:(?<channel>\i)},"notifications"\)\);))/,
|
|
|
|
replace: "if($self.isHiddenChannel($<channel>)){$<pushNotificationButtonExpression>break;}"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_FORUM:if\(!\i\){)(?=.+?;(?<pushNotificationButtonExpression>.+?{channel:(?<channel>\i)},"notifications"\)\)))/,
|
|
|
|
replace: "if($self.isHiddenChannel($<channel>)){$<pushNotificationButtonExpression>;break;}"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
match: /(?<=(?<this>\i)\.renderMobileToolbar=function.+?case \i\.\i\.GUILD_FORUM:)/,
|
|
|
|
replace: "if($self.isHiddenChannel($<this>.props.channel))break;"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
match: /(?<=renderHeaderBar=function.+?hideSearch:(?<channel>\i)\.isDirectory\(\))/,
|
|
|
|
replace: "||$self.isHiddenChannel($<channel>)"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
match: /(?<=renderSidebar=function\(\){)/,
|
|
|
|
replace: "if($self.isHiddenChannel(this.props.channel))return null;"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
match: /(?<=renderChat=function\(\){)/,
|
|
|
|
replace: "if($self.isHiddenChannel(this.props.channel))return $self.HiddenChannelLockScreen(this.props.channel);"
|
|
|
|
},
|
|
|
|
]
|
|
|
|
},
|
|
|
|
// Avoid trying to fetch messages from hidden channels
|
|
|
|
{
|
|
|
|
find: '"MessageManager"',
|
|
|
|
replacement: [
|
|
|
|
{
|
|
|
|
match: /(?<=if\(null!=(?<channelId>\i)\).{1,100}"Skipping fetch because channelId is a static route".{1,10}else{)/,
|
|
|
|
replace: "if($self.isHiddenChannel({channelId:$<channelId>}))return;"
|
|
|
|
},
|
|
|
|
]
|
|
|
|
},
|
2023-01-28 00:40:10 +00:00
|
|
|
// Patch keybind handlers so you can't accidentally jump to hidden channels
|
|
|
|
{
|
|
|
|
find: '"alt+shift+down"',
|
|
|
|
replacement: {
|
|
|
|
match: /(?<=getChannel\(\i\);return null!=(?<channel>\i))(?=.{1,130}hasRelevantUnread\(\i\))/,
|
|
|
|
replace: "&&!$self.isHiddenChannel($<channel>)"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
find: '"alt+down"',
|
|
|
|
replacement: {
|
|
|
|
match: /(?<=getState\(\)\.channelId.{1,30}\(0,\i\.\i\)\(\i\))(?=\.map\()/,
|
|
|
|
replace: ".filter(ch=>!$self.isHiddenChannel(ch))"
|
|
|
|
}
|
|
|
|
},
|
2023-02-01 11:11:05 +00:00
|
|
|
// Export the emoji component used on the lock screen
|
|
|
|
{
|
|
|
|
find: 'jumboable?"jumbo":"default"',
|
|
|
|
replacement: {
|
|
|
|
match: /(?<=\i:\(\)=>\i)(?=}.+?(?<component>\i)=function.{1,20}node,\i=\i.isInteracting)/,
|
|
|
|
replace: ",hc1:()=>$<component>" // Blame Ven length check for the small name :pensive_cry:
|
|
|
|
}
|
|
|
|
}
|
2022-10-23 09:44:21 +00:00
|
|
|
],
|
2023-01-14 22:00:29 +00:00
|
|
|
|
2023-01-25 02:35:34 +00:00
|
|
|
isHiddenChannel(channel: Channel & { channelId?: string; }) {
|
2022-10-23 09:44:21 +00:00
|
|
|
if (!channel) return false;
|
2023-01-23 21:04:50 +00:00
|
|
|
|
|
|
|
if (channel.channelId) channel = ChannelStore.getChannel(channel.channelId);
|
|
|
|
if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return false;
|
|
|
|
|
2023-01-25 02:35:34 +00:00
|
|
|
return !PermissionStore.can(Permissions.VIEW_CHANNEL, channel);
|
2022-10-23 09:44:21 +00:00
|
|
|
},
|
2023-01-14 22:00:29 +00:00
|
|
|
|
2023-02-01 11:11:05 +00:00
|
|
|
HiddenChannelLockScreen: (channel: any) => <HiddenChannelLockScreen channel={channel} />,
|
2023-01-14 22:00:29 +00:00
|
|
|
|
|
|
|
LockIcon: () => (
|
|
|
|
<svg
|
2023-01-23 21:04:50 +00:00
|
|
|
className={ChannelListClasses.icon}
|
2023-01-14 22:00:29 +00:00
|
|
|
height="18"
|
|
|
|
width="20"
|
|
|
|
viewBox="0 0 24 24"
|
2023-01-23 21:04:50 +00:00
|
|
|
aria-hidden={true}
|
|
|
|
role="img"
|
2023-01-14 22:00:29 +00:00
|
|
|
>
|
2023-02-01 11:11:05 +00:00
|
|
|
<path className="shc-evenodd-fill-current-color " d="M.7 43.05 24 2.85l23.3 40.2Zm23.55-6.25q.75 0 1.275-.525.525-.525.525-1.275 0-.75-.525-1.3t-1.275-.55q-.8 0-1.325.55-.525.55-.525 1.3t.55 1.275q.55.525 1.3.525Zm-1.85-6.1h3.65V19.4H22.4Z" />
|
2023-01-14 22:00:29 +00:00
|
|
|
</svg>
|
2023-01-23 21:04:50 +00:00
|
|
|
),
|
|
|
|
|
2023-02-01 11:11:05 +00:00
|
|
|
HiddenChannelIcon: ErrorBoundary.wrap(() => (
|
2023-01-23 21:04:50 +00:00
|
|
|
<Tooltip text="Hidden Channel">
|
|
|
|
{({ onMouseLeave, onMouseEnter }) => (
|
|
|
|
<svg
|
|
|
|
onMouseLeave={onMouseLeave}
|
|
|
|
onMouseEnter={onMouseEnter}
|
2023-02-01 11:11:05 +00:00
|
|
|
className={ChannelListClasses.icon + " " + "shc-hidden-channel-icon"}
|
2023-01-23 21:04:50 +00:00
|
|
|
width="24"
|
|
|
|
height="24"
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
aria-hidden={true}
|
|
|
|
role="img"
|
|
|
|
>
|
2023-02-01 11:11:05 +00:00
|
|
|
<path className="shc-evenodd-fill-current-color " d="m19.8 22.6-4.2-4.15q-.875.275-1.762.413Q12.95 19 12 19q-3.775 0-6.725-2.087Q2.325 14.825 1 11.5q.525-1.325 1.325-2.463Q3.125 7.9 4.15 7L1.4 4.2l1.4-1.4 18.4 18.4ZM12 16q.275 0 .512-.025.238-.025.513-.1l-5.4-5.4q-.075.275-.1.513-.025.237-.025.512 0 1.875 1.312 3.188Q10.125 16 12 16Zm7.3.45-3.175-3.15q.175-.425.275-.862.1-.438.1-.938 0-1.875-1.312-3.188Q13.875 7 12 7q-.5 0-.938.1-.437.1-.862.3L7.65 4.85q1.025-.425 2.1-.638Q10.825 4 12 4q3.775 0 6.725 2.087Q21.675 8.175 23 11.5q-.575 1.475-1.512 2.738Q20.55 15.5 19.3 16.45Zm-4.625-4.6-3-3q.7-.125 1.288.112.587.238 1.012.688.425.45.613 1.038.187.587.087 1.162Z" />
|
2023-01-23 21:04:50 +00:00
|
|
|
</svg>
|
|
|
|
)}
|
|
|
|
</Tooltip>
|
2023-02-01 11:11:05 +00:00
|
|
|
), { noop: true })
|
2022-10-23 09:44:21 +00:00
|
|
|
});
|