From a015cf96f6413c718f1acfa5c4c27a2cd4b9f594 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 19 Sep 2024 05:25:31 -0300 Subject: [PATCH 1/6] UserVoiceShow: Fix setting name --- src/plugins/userVoiceShow/components.tsx | 41 +++++++++++------------- src/plugins/userVoiceShow/index.tsx | 6 ++-- src/plugins/userVoiceShow/style.css | 10 ++++-- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index fd7dbd29e..095785dd0 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -8,7 +8,7 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildStore, IconUtils, NavigationRouter, PermissionsBits, PermissionStore, showToast, Text, Toasts, Tooltip, useCallback, useMemo, UserStore, useStateFromStores } from "@webpack/common"; +import { ChannelStore, GuildStore, IconUtils, NavigationRouter, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; import { Channel } from "discord-types/general"; const cl = classNameFactory("vc-uvs-"); @@ -17,7 +17,7 @@ const { selectVoiceChannel } = findByPropsLazy("selectChannel", "selectVoiceChan const VoiceStateStore = findStoreLazy("VoiceStateStore"); const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -interface IconProps extends React.HTMLAttributes { +interface IconProps extends React.ComponentPropsWithoutRef<"div"> { size?: number; } @@ -71,23 +71,18 @@ interface VoiceChannelTooltipProps { function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { const voiceStates = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStatesForChannel(channel.id)); + const users = useMemo( () => Object.values(voiceStates).map(voiceState => UserStore.getUser(voiceState.userId)).filter(user => user != null), [voiceStates] ); - const guild = useMemo( - () => channel.getGuildId() == null ? undefined : GuildStore.getGuild(channel.getGuildId()), - [channel] - ); - - const guildIcon = useMemo(() => { - return guild?.icon == null ? undefined : IconUtils.getGuildIconURL({ - id: guild.id, - icon: guild.icon, - size: 30 - }); - }, [guild]); + const guild = channel.getGuildId() == null ? undefined : GuildStore.getGuild(channel.getGuildId()); + const guildIcon = guild?.icon == null ? undefined : IconUtils.getGuildIconURL({ + id: guild.id, + icon: guild.icon, + size: 30 + }); return ( <> @@ -103,7 +98,7 @@ function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { @@ -119,11 +114,14 @@ const clickTimers = {} as Record; export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); - const channel = useMemo(() => channelId == null ? undefined : ChannelStore.getChannel(channelId), [channelId]); - const onClick = useCallback((e: React.MouseEvent) => { + const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); + if (channel == null) return null; + + function onClick(e: React.MouseEvent) { e.preventDefault(); e.stopPropagation(); + if (channel == null || channelId == null) return; if (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) { @@ -147,18 +145,15 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChanne delete clickTimers[channelId]; }, 250); } - }, [channelId]); + } - const isLocked = useMemo(() => { - return !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel); - }, [channelId]); - - if (channel == null) return null; + const isLocked = !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel); return ( } tooltipClassName={cl("tooltip-container")} + tooltipContentClassName={cl("tooltip-content")} > {props => isLocked ? diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index dee713b5e..5efd936ce 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -32,7 +32,7 @@ const settings = definePluginSettings({ default: true, restartNeeded: true }, - showInVoiceMemberList: { + showInMemberList: { type: OptionType.BOOLEAN, description: "Show a user's Voice Channel indicator in the member and DMs list", default: true, @@ -82,12 +82,12 @@ export default definePlugin({ match: /\.subtext,children:.+?}\)\]}\)(?=])/, replace: "$&,$self.VoiceChannelIndicator({userId:arguments[0]?.user?.id})" }, - predicate: () => settings.store.showInVoiceMemberList + predicate: () => settings.store.showInMemberList } ], start() { - if (settings.store.showInVoiceMemberList) { + if (settings.store.showInMemberList) { addDecorator("UserVoiceShow", ({ user }) => user == null ? null : ); } }, diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index b4cc00631..3e36df217 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -15,7 +15,13 @@ } .vc-uvs-tooltip-container { - max-width: 200px; + max-width: 300px; +} + +.vc-uvs-tooltip-content { + display: flex; + flex-direction: column; + gap: 6px; } .vc-uvs-guild-name { @@ -31,7 +37,5 @@ .vc-uvs-vc-members { display: flex; - margin: 8px 0; - flex-direction: row; gap: 6px; } From 755e869db7d4615f51ff2d2de8d104b2024d7760 Mon Sep 17 00:00:00 2001 From: adryd Date: Thu, 19 Sep 2024 19:31:20 -0400 Subject: [PATCH 2/6] clearURLs: Add si@soundcloud.com to rule list (#2890) --- src/plugins/clearURLs/defaultRules.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/clearURLs/defaultRules.ts b/src/plugins/clearURLs/defaultRules.ts index b5aae5ff3..e4e7d380c 100644 --- a/src/plugins/clearURLs/defaultRules.ts +++ b/src/plugins/clearURLs/defaultRules.ts @@ -155,4 +155,5 @@ export const defaultRules = [ "igshid", "igsh", "share_id@reddit.com", + "si@soundcloud.com", ]; From f7587d9b2eb12ddb0e0a0020d69f26a105335cf6 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 20 Sep 2024 02:03:42 +0200 Subject: [PATCH 3/6] ShowHiddenThings: fix discovery keyword filter bypass --- src/plugins/showHiddenThings/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts index 9ffaa7e14..847dcd327 100644 --- a/src/plugins/showHiddenThings/index.ts +++ b/src/plugins/showHiddenThings/index.ts @@ -112,12 +112,12 @@ export default definePlugin({ }, // patch request that queries if term is allowed { - find: ".GUILD_DISCOVERY_VALID_TERM", + find: ".GUILD_DISCOVERY_VALID_TERM,query:", predicate: () => settings.store.disableDisallowedDiscoveryFilters, all: true, replacement: { - match: /\i\.\i\.get\(\{url:\i\.\i\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\);/g, - replace: "Promise.resolve({ body: { valid: true } });" + match: /\i\.\i\.get\(\{url:\i\.\i\.GUILD_DISCOVERY_VALID_TERM,query:\{term:\i\},oldFormErrors:!0\}\)/g, + replace: "Promise.resolve({ body: { valid: true } })" } } ], From e8242f22c998ffdc50fa9e663c40c3da4d7fc4d8 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:06:26 -0300 Subject: [PATCH 4/6] UserVoiceShow: Better support for DM channels --- src/plugins/userVoiceShow/components.tsx | 63 +++++++++++++++++------- src/plugins/userVoiceShow/index.tsx | 6 +-- src/plugins/userVoiceShow/style.css | 15 +++++- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index 095785dd0..fad860dfa 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -7,15 +7,22 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; -import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, GuildStore, IconUtils, NavigationRouter, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; +import { filters, findByCodeLazy, findByPropsLazy, findComponentByCodeLazy, findStoreLazy, mapMangledModuleLazy } from "@webpack"; +import { ChannelStore, GuildStore, IconUtils, match, NavigationRouter, P, PermissionsBits, PermissionStore, React, showToast, Text, Toasts, Tooltip, useMemo, UserStore, useStateFromStores } from "@webpack/common"; import { Channel } from "discord-types/general"; const cl = classNameFactory("vc-uvs-"); -const { selectVoiceChannel } = findByPropsLazy("selectChannel", "selectVoiceChannel"); +const { selectVoiceChannel } = findByPropsLazy("selectVoiceChannel", "selectChannel"); +const { useChannelName } = mapMangledModuleLazy(".Messages.GROUP_DM_ALONE", { + useChannelName: filters.byCode("()=>null==") +}); +const getDMChannelIcon = findByCodeLazy(".getChannelIconURL({"); const VoiceStateStore = findStoreLazy("VoiceStateStore"); + const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const Avatar = findComponentByCodeLazy(".AVATAR_STATUS_TYPING_16;"); +const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL"); interface IconProps extends React.ComponentPropsWithoutRef<"div"> { size?: number; @@ -28,7 +35,7 @@ function SpeakerIcon(props: IconProps) {
{ + return channel.recipients.length >= 2 && channel.icon == null + ? + : ; + }) + .otherwise(() => null); + const channelName = useChannelName(channel); + return ( <> {guild != null && ( -
+
{guildIcon != null && } {guild.name}
)} - {channel.name} +
+ {channelIcon} + {channelName} +
; -export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChannelIndicatorProps) => { +export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActionButton }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); if (channel == null) return null; + const isDM = channel.isDM() || channel.isMultiUserDM(); + const isLocked = !isDM && (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel)); + function onClick(e: React.MouseEvent) { e.preventDefault(); e.stopPropagation(); if (channel == null || channelId == null) return; - if (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) { + if (!isDM && !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) { showToast("You cannot view the user's Voice Channel", Toasts.Type.FAILURE); return; } @@ -133,7 +157,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChanne delete clickTimers[channelId]; if (e.detail > 1) { - if (!PermissionStore.can(PermissionsBits.CONNECT, channel)) { + if (!isDM && !PermissionStore.can(PermissionsBits.CONNECT, channel)) { showToast("You cannot join the user's Voice Channel", Toasts.Type.FAILURE); return; } @@ -147,19 +171,24 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId }: VoiceChanne } } - const isLocked = !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel); - return ( } tooltipClassName={cl("tooltip-container")} tooltipContentClassName={cl("tooltip-content")} > - {props => - isLocked ? - - : - } + {props => { + const iconProps = { + ...props, + onClick, + size, + className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding") + }; + + return isLocked ? + + : ; + }} ); }, { noop: true }); diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 5efd936ce..573fd0e38 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -77,10 +77,10 @@ export default definePlugin({ }, */ // Friends List { - find: ".avatar,animate:", + find: "null!=this.peopleListItemRef.current", replacement: { - match: /\.subtext,children:.+?}\)\]}\)(?=])/, - replace: "$&,$self.VoiceChannelIndicator({userId:arguments[0]?.user?.id})" + match: /\.actions,children:\[/, + replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,size:20,isActionButton:true})," }, predicate: () => settings.store.showInMemberList } diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index 3e36df217..67f4c4958 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -1,6 +1,5 @@ .vc-uvs-speaker { color: var(--interactive-normal); - padding: 0 4px; display: flex; align-items: center; justify-content: center; @@ -14,6 +13,18 @@ color: var(--interactive-hover); } +.vc-uvs-speaker-padding { + padding: 0 4px; +} + +.vc-uvs-indicator-action-button { + background-color: var(--background-secondary); + border-radius: 100%; + height: 36px; + width: 36px; + margin-left: 10px; +} + .vc-uvs-tooltip-container { max-width: 300px; } @@ -24,7 +35,7 @@ gap: 6px; } -.vc-uvs-guild-name { +.vc-uvs-name { display: flex; align-items: center; gap: 8px; From 467157539c65d00b66bbd8d5cdc477d6951d6642 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:16:16 -0300 Subject: [PATCH 5/6] Bump to 1.10.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e65e1b0a7..88633f65c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.10.1", + "version": "1.10.2", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 10188ead070628fd5a994f865af248396921a4bf Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:42:00 -0300 Subject: [PATCH 6/6] UserVoiceShow: Show in messages --- src/plugins/userVoiceShow/components.tsx | 20 +++++++++++--------- src/plugins/userVoiceShow/index.tsx | 15 +++++++++++++-- src/plugins/userVoiceShow/style.css | 8 ++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx index fad860dfa..f248cf72c 100644 --- a/src/plugins/userVoiceShow/components.tsx +++ b/src/plugins/userVoiceShow/components.tsx @@ -127,13 +127,13 @@ function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) { interface VoiceChannelIndicatorProps { userId: string; - size?: number; isActionButton?: boolean; + isMessageIndicator?: boolean; } const clickTimers = {} as Record; -export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActionButton }: VoiceChannelIndicatorProps) => { +export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isActionButton, isMessageIndicator }: VoiceChannelIndicatorProps) => { const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined); const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId); @@ -178,16 +178,18 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio tooltipContentClassName={cl("tooltip-content")} > {props => { - const iconProps = { + const iconProps: IconProps = { ...props, - onClick, - size, - className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding") + className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding"), + size: isActionButton ? 20 : undefined, + onClick }; - return isLocked ? - - : ; + return
+ {isLocked ? + + : } +
; }} ); diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index 573fd0e38..d30c5b7f9 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -19,6 +19,7 @@ import "./style.css"; import { addDecorator, removeDecorator } from "@api/MemberListDecorators"; +import { addDecoration, removeDecoration } from "@api/MessageDecorations"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; @@ -37,13 +38,19 @@ const settings = definePluginSettings({ description: "Show a user's Voice Channel indicator in the member and DMs list", default: true, restartNeeded: true + }, + showInMessages: { + type: OptionType.BOOLEAN, + description: "Show a user's Voice Channel indicator in messages", + default: true, + restartNeeded: true } }); export default definePlugin({ name: "UserVoiceShow", description: "Shows an indicator when a user is in a Voice Channel", - authors: [Devs.LordElias, Devs.Nuckyz], + authors: [Devs.Nuckyz, Devs.LordElias], settings, patches: [ @@ -80,7 +87,7 @@ export default definePlugin({ find: "null!=this.peopleListItemRef.current", replacement: { match: /\.actions,children:\[/, - replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,size:20,isActionButton:true})," + replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true})," }, predicate: () => settings.store.showInMemberList } @@ -90,10 +97,14 @@ export default definePlugin({ if (settings.store.showInMemberList) { addDecorator("UserVoiceShow", ({ user }) => user == null ? null : ); } + if (settings.store.showInMessages) { + addDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : ); + } }, stop() { removeDecorator("UserVoiceShow"); + removeDecoration("UserVoiceShow"); }, VoiceChannelIndicator diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css index 67f4c4958..072dee941 100644 --- a/src/plugins/userVoiceShow/style.css +++ b/src/plugins/userVoiceShow/style.css @@ -17,6 +17,14 @@ padding: 0 4px; } +.vc-uvs-message-indicator { + display: inline-flex; + align-items: center; + justify-content: center; + top: 2.5px; + position: relative; +} + .vc-uvs-indicator-action-button { background-color: var(--background-secondary); border-radius: 100%;