diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx index 50a6f527..8c7fa114 100644 --- a/src/plugins/messageLogger/index.tsx +++ b/src/plugins/messageLogger/index.tsx @@ -23,8 +23,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import Logger from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; -import { Parser, UserStore } from "@webpack/common"; +import { moment, Parser, Timestamp, UserStore } from "@webpack/common"; function addDeleteStyleClass() { if (Settings.plugins.MessageLogger.deleteStyle === "text") { @@ -41,13 +40,7 @@ export default definePlugin({ description: "Temporarily logs deleted and edited messages.", authors: [Devs.rushii, Devs.Ven], - timestampModule: null as any, - moment: null as Function | null, - start() { - this.moment = findByPropsLazy("relativeTimeRounding", "relativeTimeThreshold"); - this.timestampModule = findByPropsLazy("messageLogger_TimestampComponent"); - addDeleteStyleClass(); }, @@ -59,7 +52,6 @@ export default definePlugin({ }, renderEdit(edit: { timestamp: any, content: string; }) { - const Timestamp = this.timestampModule.messageLogger_TimestampComponent; return (
@@ -78,7 +70,7 @@ export default definePlugin({ makeEdit(newMessage: any, oldMessage: any): any { return { - timestamp: this.moment?.call(newMessage.edited_timestamp), + timestamp: moment?.call(newMessage.edited_timestamp), content: oldMessage.content }; }, @@ -312,17 +304,6 @@ export default definePlugin({ ] }, - { - // Message "(edited)" timestamp component - // Module 23552 - find: "Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format", - replacement: { - // Re-export the timestamp component under a findable name - match: /{(\w{1,2}:\(\)=>(\w{1,2}))}/, - replace: "{$1,messageLogger_TimestampComponent:()=>$2}" - } - }, - { // Message context base menu // Module 600300 diff --git a/src/plugins/showHiddenChannels.tsx b/src/plugins/showHiddenChannels.tsx index a97259a6..1225cf11 100644 --- a/src/plugins/showHiddenChannels.tsx +++ b/src/plugins/showHiddenChannels.tsx @@ -23,125 +23,177 @@ import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; import { ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; -import { Button, ChannelStore, PermissionStore, SnowflakeUtils, Text } from "@webpack/common"; +import { findByPropsLazy } from "@webpack"; +import { Button, ChannelStore, moment, Parser, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip } from "@webpack/common"; + +const ChannelListClasses = findByPropsLazy("channelName", "subtitle", "modeMuted", "iconContainer"); -const CONNECT = 1048576n; const VIEW_CHANNEL = 1024n; +enum ChannelTypes { + GUILD_TEXT = 0, + GUILD_ANNOUNCEMENT = 5, + GUILD_FORUM = 15 +} + +const ChannelTypesToChannelName = { + [ChannelTypes.GUILD_TEXT]: "TEXT", + [ChannelTypes.GUILD_ANNOUNCEMENT]: "ANNOUNCEMENT", + [ChannelTypes.GUILD_FORUM]: "FORUM" +}; + +enum ShowMode { + LockIcon, + HiddenIconWithMutedStyle +} + export default definePlugin({ name: "ShowHiddenChannels", - description: "Show hidden channels", - authors: [Devs.BigDuck, Devs.AverageReactEnjoyer, Devs.D3SOX, Devs.Ven], + description: "Show channels that you do not have access to view.", + authors: [Devs.BigDuck, Devs.AverageReactEnjoyer, Devs.D3SOX, Devs.Ven, Devs.Nuckyz, Devs.Nickyux], options: { hideUnreads: { - description: "Hide unreads", + description: "Hide Unreads", type: OptionType.BOOLEAN, default: true, - restartNeeded: true // Restart is needed to refresh channel list + 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 } }, patches: [ { // RenderLevel defines if a channel is hidden, collapsed in category, visible, etc find: ".CannotShow", - replacement: { - match: /renderLevel:(\w+)\.CannotShow/g, - replace: "renderLevel:Vencord.Plugins.plugins.ShowHiddenChannels.shouldShow(this.record, this.category, this.isMuted)?$1.Show:$1.CannotShow" - } + // These replacements only change the necessary CannotShow's + replacement: [ + { + match: /(?renderLevel:(?\i\(this,\i\)\?\i\.Show:\i\.WouldShowIfUncollapsed).+?renderLevel:).+?,/, + replace: "$$," + }, + { + match: /(?activeJoinedRelevantThreads.{1,100}renderLevel:(?\i)\.Show.+?renderLevel:).+?,/, + replace: "$$.Show," + }, + { + match: /(?isChannelGatedAndVisible\(this\.record\.guild_id,this\.record\.id\).+?renderLevel:)(?\i)\.CannotShow/, + replace: "$this.category.isCollapsed?$.WouldShowIfUncollapsed:$.Show" + }, + { + match: /(?getRenderLevel=function.+?return).+?\?(?.+?):\i\.CannotShow}/, + replace: "$ $}" + } + ] }, { // inside the onMouseClick handler, we check if the channel is hidden and open the modal if it is find: ".handleThreadsPopoutClose();", replacement: { - match: /((\w)\.handleThreadsPopoutClose\(\);)/g, - replace: "if(arguments[0].button===0&&Vencord.Plugins.plugins.ShowHiddenChannels.channelSelected($2?.props?.channel))return;$1" + match: /(?\i)\.handleThreadsPopoutClose\(\);/, + replace: "if(arguments[0].button===0&&$self.channelSelected($?.props?.channel))return;$&" } }, { - // Prevent categories from disappearing when they're collapsed - find: ".prototype.shouldShowEmptyCategory=function(){", - replacement: { - match: /(\.prototype\.shouldShowEmptyCategory=function\(\){)/g, - replace: "$1return true;" - } - }, - { - // Hide unreads - find: "?\"button\":\"link\"", + find: ".UNREAD_HIGHLIGHT", predicate: () => Settings.plugins.ShowHiddenChannels.hideUnreads === true, + replacement: [{ + // Hide unreads + match: /(?\i\.connected,)(?\i)=(?\i).unread/, + replace: "$$=$self.isHiddenChannel($.channel)?false:$.unread" + }] + }, + { + find: ".Messages.CHANNEL_TOOLTIP_DIRECTORY", + predicate: () => Settings.plugins.ShowHiddenChannels.showMode === ShowMode.LockIcon, 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" + // Lock Icon + match: /switch\((?\i)\.type\).{1,30}\.GUILD_ANNOUNCEMENT.{1,30}\(0,\i\.\i\)\(\i\)/, + replace: "if($self.isHiddenChannel($))return $self.LockIcon;$&" } }, + { + find: ".UNREAD_HIGHLIGHT", + predicate: () => Settings.plugins.ShowHiddenChannels.showMode === ShowMode.HiddenIconWithMutedStyle, + replacement: [ + // Make the channel appear as muted if it's hidden + { + match: /(?\i\.name,)(?\i)=(?\i).muted/, + replace: "$$=$self.isHiddenChannel($.channel)?true:$.muted" + }, + // Add the hidden eye icon if the channel is hidden + { + match: /channel:(?\i),.+?\.channelName.+?\.children.+?:null/, + replace: "$&,$self.isHiddenChannel($)?$self.HiddenChannelIcon():null" + }, + // Make voice channels also appear as muted if they are muted + { + match: /(?.wrapper:\i\(\).notInteractive,)(?.+?)(?(?\i)\?\i\.MUTED:)/, + replace: "$$\"\",$$?\"\":" + } + ] + }, { // Hide New unreads box for hidden channels find: '.displayName="ChannelListUnreadsStore"', replacement: { - match: /((.)\.getGuildId\(\))(&&\(!\(.\.isThread.{1,100}\.hasRelevantUnread\()/, - replace: "$1&&!$2._isHiddenChannel$3" + match: /(?return null!=(?\i))(?&&null!=\i\.getGuildId\(\).{1,120}hasRelevantUnread\(\i\)\))/, + replace: "$&&!$self.isHiddenChannel($)$" } }, - // Lock Icon - { - find: ".rulesChannelId))", - replacement: { - match: /(\.locked.{0,400})(switch\((\i)\.type\))/, - replace: "$1 if($3._isHiddenChannel)return $self.LockIcon;$2" - } - } ], - shouldShow(channel, category, isMuted) { - if (!this.isHiddenChannel(channel)) return false; - if (!category) return false; - if (channel.type === 0 && category.guild?.hideMutedChannels && isMuted) return false; - - return !category.isCollapsed; - }, - isHiddenChannel(channel) { if (!channel) return false; - if (channel.channelId) - channel = ChannelStore.getChannel(channel.channelId); - if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) - return false; - // check for disallowed voice channels too so that they get hidden when collapsing the category - channel._isHiddenChannel = !PermissionStore.can(VIEW_CHANNEL, channel) || (channel.type === 2 && !PermissionStore.can(CONNECT, channel)); - return channel._isHiddenChannel; + if (channel.channelId) channel = ChannelStore.getChannel(channel.channelId); + if (!channel || channel.isDM() || channel.isGroupDM() || channel.isMultiUserDM()) return false; + + return !PermissionStore.can(VIEW_CHANNEL, channel); }, channelSelected(channel) { if (!channel) return false; + const isHidden = this.isHiddenChannel(channel); - // check for type again, otherwise it would show it for hidden stage channels - if (channel.type === 0 && isHidden) { - const lastMessageDate = channel.lastMessageId ? new Date(SnowflakeUtils.extractTimestamp(channel.lastMessageId)).toLocaleString() : null; + + // Check for type, otherwise it would attempt to show the modal for stage channels + if ([ChannelTypes.GUILD_TEXT, ChannelTypes.GUILD_ANNOUNCEMENT, ChannelTypes.GUILD_FORUM].includes(channel.type) && isHidden) { openModal(modalProps => ( - {channel.name} + #{channel.name} + {} {channel.isNSFW() && } - You don't have the permission to view the messages in this channel. - {(channel.topic || "").length > 0 && ( + You don't have permission to view {channel.type === ChannelTypes.GUILD_FORUM ? "posts" : "messages"} in this channel. + {(channel.topic ?? "").length > 0 && ( <> - Topic: + {channel.type === ChannelTypes.GUILD_FORUM ? "Guidelines:" : "Topic:"} - {channel.topic} +
+ {Parser.parseTopic(channel.topic, true, { channelId: channel.id })} +
)} - {lastMessageDate && ( + {channel.lastMessageId && ( <> - Last message sent: + {channel.type === ChannelTypes.GUILD_FORUM ? "Last Post Created" : "Last Message Sent:"} - {lastMessageDate} +
+ +
)}
@@ -164,11 +216,34 @@ export default definePlugin({ LockIcon: () => ( - + + ), + + HiddenChannelIcon: () => ( + + {({ onMouseLeave, onMouseEnter }) => ( + + + + )} + ) }); diff --git a/src/webpack/common.tsx b/src/webpack/common.tsx index 0be47ff7..562332ad 100644 --- a/src/webpack/common.tsx +++ b/src/webpack/common.tsx @@ -75,6 +75,7 @@ export let Button: any; export const ButtonLooks = findByPropsLazy("BLANK", "FILLED", "INVERTED") as Record<"FILLED" | "INVERTED" | "OUTLINED" | "LINK" | "BLANK", string>; export let Switch: any; export let Tooltip: Components.Tooltip; +export let Timestamp: any; export let Router: any; export let TextInput: any; export let Text: (props: TextProps) => JSX.Element; @@ -185,6 +186,8 @@ waitFor(["Hovers", "Looks", "Sizes"], m => Button = m); waitFor(filters.byCode("tooltipNote", "ringTarget"), m => Switch = m); +waitFor(filters.byCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format"), m => Timestamp = m); + waitFor(["Positions", "Colors"], m => Tooltip = m); waitFor(m => m.Types?.PRIMARY === "cardPrimary", m => Card = m); @@ -307,4 +310,3 @@ export const ContextMenu = mapMangledModuleLazy('type:"CONTEXT_MENU_OPEN"', { export const MaskedLinkStore = mapMangledModuleLazy('"MaskedLinkStore"', { openUntrustedLink: filters.byCode(".apply(this,arguments)") }); -