From 49b0a38c37c58856048958666c133e99035656a8 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 01/18] UserVoiceShow: Show in messages
---
src/plugins/crashHandler/index.ts | 2 +-
src/plugins/keepCurrentChannel/index.ts | 14 +++++-------
src/plugins/userVoiceShow/components.tsx | 27 ++++++++++++++----------
src/plugins/userVoiceShow/index.tsx | 19 +++++++++++++----
src/plugins/userVoiceShow/style.css | 14 ++++++------
src/webpack/common/types/utils.d.ts | 7 +++++-
src/webpack/common/utils.ts | 4 ++++
7 files changed, 53 insertions(+), 34 deletions(-)
diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts
index ab881e60..221b115f 100644
--- a/src/plugins/crashHandler/index.ts
+++ b/src/plugins/crashHandler/index.ts
@@ -175,7 +175,7 @@ export default definePlugin({
}
if (settings.store.attemptToNavigateToHome) {
try {
- NavigationRouter.transitionTo("/channels/@me");
+ NavigationRouter.transitionToGuild("@me");
} catch (err) {
CrashHandlerLogger.debug("Failed to navigate to home", err);
}
diff --git a/src/plugins/keepCurrentChannel/index.ts b/src/plugins/keepCurrentChannel/index.ts
index b226c34e..1e0e742d 100644
--- a/src/plugins/keepCurrentChannel/index.ts
+++ b/src/plugins/keepCurrentChannel/index.ts
@@ -19,7 +19,7 @@
import * as DataStore from "@api/DataStore";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
-import { ChannelStore, NavigationRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common";
+import { ChannelRouter, SelectedChannelStore, SelectedGuildStore } from "@webpack/common";
export interface LogoutEvent {
type: "LOGOUT";
@@ -40,11 +40,6 @@ interface PreviousChannel {
let isSwitchingAccount = false;
let previousCache: PreviousChannel | undefined;
-function attemptToNavigateToChannel(guildId: string | null, channelId: string) {
- if (!ChannelStore.hasChannel(channelId)) return;
- NavigationRouter.transitionTo(`/channels/${guildId ?? "@me"}/${channelId}`);
-}
-
export default definePlugin({
name: "KeepCurrentChannel",
description: "Attempt to navigate to the channel you were in before switching accounts or loading Discord.",
@@ -59,8 +54,9 @@ export default definePlugin({
if (!isSwitchingAccount) return;
isSwitchingAccount = false;
- if (previousCache?.channelId)
- attemptToNavigateToChannel(previousCache.guildId, previousCache.channelId);
+ if (previousCache?.channelId) {
+ ChannelRouter.transitionToChannel(previousCache.channelId);
+ }
},
async CHANNEL_SELECT({ guildId, channelId }: ChannelSelectEvent) {
@@ -84,7 +80,7 @@ export default definePlugin({
await DataStore.set("KeepCurrentChannel_previousData", previousCache);
} else if (previousCache.channelId) {
- attemptToNavigateToChannel(previousCache.guildId, previousCache.channelId);
+ ChannelRouter.transitionToChannel(previousCache.channelId);
}
}
});
diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx
index fad860df..f9a81c4b 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 { 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 { ChannelRouter, ChannelStore, GuildStore, IconUtils, match, 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-");
@@ -24,6 +24,8 @@ const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaul
const Avatar = findComponentByCodeLazy(".AVATAR_STATUS_TYPING_16;");
const GroupDMAvatars = findComponentByCodeLazy(".AvatarSizeSpecs[", "getAvatarURL");
+const ActionButtonClasses = findByPropsLazy("actionButton", "highlight");
+
interface IconProps extends React.ComponentPropsWithoutRef<"div"> {
size?: number;
}
@@ -74,9 +76,10 @@ function LockedSpeakerIcon(props: IconProps) {
interface VoiceChannelTooltipProps {
channel: Channel;
+ isLocked: boolean;
}
-function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) {
+function VoiceChannelTooltip({ channel, isLocked }: VoiceChannelTooltipProps) {
const voiceStates = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStatesForChannel(channel.id));
const users = useMemo(
@@ -113,7 +116,7 @@ function VoiceChannelTooltip({ channel }: VoiceChannelTooltipProps) {
{channelName}
-
+ {isLocked ?
:
}
;
-export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActionButton }: VoiceChannelIndicatorProps) => {
+export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndicator, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined);
const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId);
@@ -165,7 +170,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio
selectVoiceChannel(channelId);
} else {
clickTimers[channelId] = setTimeout(() => {
- NavigationRouter.transitionTo(`/channels/${channel.getGuildId() ?? "@me"}/${channelId}`);
+ ChannelRouter.transitionToChannel(channelId);
delete clickTimers[channelId];
}, 250);
}
@@ -173,16 +178,16 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, size, isActio
return (
}
+ text={}
tooltipClassName={cl("tooltip-container")}
tooltipContentClassName={cl("tooltip-content")}
>
{props => {
- const iconProps = {
+ const iconProps: IconProps = {
...props,
- onClick,
- size,
- className: isActionButton ? cl("indicator-action-button") : cl("speaker-padding")
+ className: classes(isMessageIndicator && cl("message-indicator"), (!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight),
+ size: isActionButton ? 20 : undefined,
+ onClick
};
return isLocked ?
diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx
index 573fd0e3..98386a16 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: [
@@ -52,7 +59,7 @@ export default definePlugin({
find: ".Messages.USER_PROFILE_LOAD_ERROR",
replacement: {
match: /(\.fetchError.+?\?)null/,
- replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId})`
+ replace: (_, rest) => `${rest}$self.VoiceChannelIndicator({userId:arguments[0]?.userId,isProfile:true})`
},
predicate: () => settings.store.showInUserProfileModal
},
@@ -79,8 +86,8 @@ export default definePlugin({
{
find: "null!=this.peopleListItemRef.current",
replacement: {
- match: /\.actions,children:\[/,
- replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,size:20,isActionButton:true}),"
+ match: /\.actions,children:\[(?<=isFocused:(\i).+?)/,
+ replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true,shouldHighlight:$1}),"
},
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 67f4c495..d172975b 100644
--- a/src/plugins/userVoiceShow/style.css
+++ b/src/plugins/userVoiceShow/style.css
@@ -13,16 +13,14 @@
color: var(--interactive-hover);
}
-.vc-uvs-speaker-padding {
- padding: 0 4px;
+.vc-uvs-speaker-margin {
+ margin-left: 4px;
}
-.vc-uvs-indicator-action-button {
- background-color: var(--background-secondary);
- border-radius: 100%;
- height: 36px;
- width: 36px;
- margin-left: 10px;
+.vc-uvs-message-indicator {
+ display: inline-flex;
+ top: 2.5px;
+ position: relative;
}
.vc-uvs-tooltip-container {
diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts
index dd76d1ad..c0a93004 100644
--- a/src/webpack/common/types/utils.d.ts
+++ b/src/webpack/common/types/utils.d.ts
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { Guild, GuildMember, User } from "discord-types/general";
+import { Channel, Guild, GuildMember, User } from "discord-types/general";
import type { ReactNode } from "react";
import { LiteralUnion } from "type-fest";
@@ -173,6 +173,11 @@ export interface NavigationRouter {
transitionToGuild(guildId: string, ...args: unknown[]): void;
}
+export interface ChannelRouter {
+ transitionToChannel: (channelId: string) => void;
+ transitionToThread: (channel: Channel) => void;
+}
+
export interface IconUtils {
getUserAvatarURL(user: User, canAnimate?: boolean, size?: number, format?: string): string;
getDefaultAvatarURL(id: string, discriminator?: string): string;
diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts
index b557f4da..2d0026b5 100644
--- a/src/webpack/common/utils.ts
+++ b/src/webpack/common/utils.ts
@@ -149,6 +149,10 @@ export const NavigationRouter: t.NavigationRouter = mapMangledModuleLazy("Transi
back: filters.byCode("goBack()"),
forward: filters.byCode("goForward()"),
});
+export const ChannelRouter: t.ChannelRouter = mapMangledModuleLazy('"Thread must have a parent ID."', {
+ transitionToChannel: filters.byCode(".preload"),
+ transitionToThread: filters.byCode('"Thread must have a parent ID."')
+});
export let SettingsRouter: any;
waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m);
From 2d675b4b2e4c797315aff657298de96d07e4bbf1 Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Sat, 21 Sep 2024 08:43:13 -0300
Subject: [PATCH 02/18] ReviewDB: Fix in panel profile (again)
---
src/plugins/reviewDB/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx
index 9d93e53a..822ebde6 100644
--- a/src/plugins/reviewDB/index.tsx
+++ b/src/plugins/reviewDB/index.tsx
@@ -91,7 +91,7 @@ export default definePlugin({
}
},
{
- find: ".PANEL,interactionType:",
+ find: 'location:"UserProfilePanel"',
replacement: {
match: /{profileType:\i\.\i\.PANEL,children:\[/,
replace: "$&$self.BiteSizeReviewsButton({user:arguments[0].user}),"
From 492b0cff0888452096d5c2ba45258e769f4f4ff1 Mon Sep 17 00:00:00 2001
From: Joona <69722179+Masterjoona@users.noreply.github.com>
Date: Sat, 21 Sep 2024 18:22:19 +0300
Subject: [PATCH 03/18] OpenInApp: Fix opening in spotify activity cards for
web (#2894)
---
src/plugins/openInApp/index.ts | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts
index 7b62831f..576980cb 100644
--- a/src/plugins/openInApp/index.ts
+++ b/src/plugins/openInApp/index.ts
@@ -100,6 +100,20 @@ export default definePlugin({
replace: "true$1VencordNative.native.openExternal"
}
},
+ {
+ find: "no artist ids in metadata",
+ predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify,
+ replacement: [
+ {
+ match: /\i\.\i\.isProtocolRegistered\(\)/g,
+ replace: "true"
+ },
+ {
+ match: /!\(0,\i\.isDesktop\)\(\)/,
+ replace: "false"
+ }
+ ]
+ },
{
find: ".CONNECTED_ACCOUNT_VIEWED,",
replacement: {
From 1dc2d924932f29ccf7422ac51eb0fac90490634f Mon Sep 17 00:00:00 2001
From: Drew <84212701+MrDiamondDog@users.noreply.github.com>
Date: Sat, 21 Sep 2024 13:10:46 -0600
Subject: [PATCH 04/18] ReplaceGoogleSearch: Fix DuckDuckGo URL (#2895)
---
src/plugins/replaceGoogleSearch/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/replaceGoogleSearch/index.tsx b/src/plugins/replaceGoogleSearch/index.tsx
index 43b0762a..593c9863 100644
--- a/src/plugins/replaceGoogleSearch/index.tsx
+++ b/src/plugins/replaceGoogleSearch/index.tsx
@@ -12,7 +12,7 @@ import { Flex, Menu } from "@webpack/common";
const DefaultEngines = {
Google: "https://www.google.com/search?q=",
- DuckDuckGo: "https://duckduckgo.com/",
+ DuckDuckGo: "https://duckduckgo.com/?q=",
Brave: "https://search.brave.com/search?q=",
Bing: "https://www.bing.com/search?q=",
Yahoo: "https://search.yahoo.com/search?p=",
From 22a5b18bfa0b736acc1a0393fe1ad3a82f828dc1 Mon Sep 17 00:00:00 2001
From: DokterKaj <54882101+DokterKaj@users.noreply.github.com>
Date: Sun, 22 Sep 2024 03:12:20 +0800
Subject: [PATCH 05/18] CopyFileContents: Add padding to button (#2848)
---
src/plugins/copyFileContents/style.css | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/plugins/copyFileContents/style.css b/src/plugins/copyFileContents/style.css
index c643cf0f..91034bf2 100644
--- a/src/plugins/copyFileContents/style.css
+++ b/src/plugins/copyFileContents/style.css
@@ -1,6 +1,7 @@
.vc-cfc-button {
color: var(--interactive-normal);
cursor: pointer;
+ padding-left: 4px;
}
.vc-cfc-button:hover {
From eaf62d8c1cd8ea7997e6efde04317e5b4700afbe Mon Sep 17 00:00:00 2001
From: Kyuuhachi <1547062+Kyuuhachi@users.noreply.github.com>
Date: Sun, 22 Sep 2024 09:11:07 +0200
Subject: [PATCH 06/18] RoleColorEverywhere: Add coloring to message contents
(#2893)
---
src/plugins/roleColorEverywhere/index.tsx | 40 ++++++++++++++++++++---
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx
index b5f66c09..e3b22fd6 100644
--- a/src/plugins/roleColorEverywhere/index.tsx
+++ b/src/plugins/roleColorEverywhere/index.tsx
@@ -18,10 +18,14 @@
import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
+import { makeRange } from "@components/PluginSettings/components";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
+import { findByCodeLazy } from "@webpack";
import { ChannelStore, GuildMemberStore, GuildStore } from "@webpack/common";
+const useMessageAuthor = findByCodeLazy('"Result cannot be null because the message is not null"');
+
const settings = definePluginSettings({
chatMentions: {
type: OptionType.BOOLEAN,
@@ -46,13 +50,21 @@ const settings = definePluginSettings({
default: true,
description: "Show role colors in the reactors list",
restartNeeded: true
- }
+ },
+ messageSaturation: {
+ type: OptionType.SLIDER,
+ description: "Intensity of message coloring. 0 to disable.",
+ markers: makeRange(0, 100, 10),
+ default: 30,
+ // This is called only once at startup, but late enough that the store is initialized.
+ get restartNeeded() { return settings.store.messageSaturation === 0; }
+ },
});
export default definePlugin({
name: "RoleColorEverywhere",
- authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN],
+ authors: [Devs.KingFish, Devs.lewisakura, Devs.AutumnVN, Devs.Kyuuhachi],
description: "Adds the top role color anywhere possible",
patches: [
// Chat Mentions
@@ -114,7 +126,15 @@ export default definePlugin({
replace: "$&,style:{color:$self.getColor($2?.id,$1)}"
},
predicate: () => settings.store.reactorsList,
- }
+ },
+ {
+ find: '.Messages.MESSAGE_EDITED,")"',
+ replacement: {
+ match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/,
+ replace: "style:{color:$self.useMessageColor($1)},"
+ },
+ predicate: () => settings.store.messageSaturation !== 0,
+ },
],
settings,
@@ -148,5 +168,17 @@ export default definePlugin({
color: this.getColor(userId, { guildId })
}
};
- }
+ },
+
+ useMessageColor(message: any) {
+ try {
+ const { messageSaturation } = settings.use(["messageSaturation"]);
+ const author = useMessageAuthor(message);
+ if (author.colorString !== undefined && messageSaturation !== 0)
+ return `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var(--text-normal))`;
+ } catch(e) {
+ console.error("[RCE] failed to get message color", e);
+ }
+ return undefined;
+ },
});
From e4318a887a70c9bf70888c55bec09e33efb2351d Mon Sep 17 00:00:00 2001
From: sadan4 <117494111+sadan4@users.noreply.github.com>
Date: Sun, 22 Sep 2024 03:24:12 -0400
Subject: [PATCH 07/18] ConsoleJanitor: Ignore all loggers with whitelist
(#2896)
---
src/plugins/consoleJanitor/README.md | 4 +-
src/plugins/consoleJanitor/index.ts | 61 ++++++++++++++--------------
2 files changed, 32 insertions(+), 33 deletions(-)
diff --git a/src/plugins/consoleJanitor/README.md b/src/plugins/consoleJanitor/README.md
index fbba766a..9737f53d 100644
--- a/src/plugins/consoleJanitor/README.md
+++ b/src/plugins/consoleJanitor/README.md
@@ -1,5 +1,5 @@
# ConsoleJanitor
-Disables annoying console messages/errors. This plugin mainly removes errors/warnings that happen all the time and noisy/spammy logging messages.
+Disables annoying console messages/errors. This plugin mainly removes errors/warnings that happen all the time and Discord logger messages.
-Some of the disabled messages include the "notosans-400-normalitalic" error and MessageActionCreators, Routing/Utils loggers.
+One of the disabled messages is the "Window state not initialized" warning, for example.
diff --git a/src/plugins/consoleJanitor/index.ts b/src/plugins/consoleJanitor/index.ts
index f5f43c06..b0c8905f 100644
--- a/src/plugins/consoleJanitor/index.ts
+++ b/src/plugins/consoleJanitor/index.ts
@@ -6,7 +6,7 @@
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
-import definePlugin, { OptionType } from "@utils/types";
+import definePlugin, { OptionType, StartAt } from "@utils/types";
const Noop = () => { };
const NoopLogger = {
@@ -22,10 +22,12 @@ const NoopLogger = {
fileOnly: Noop
};
+const logAllow = new Set();
+
const settings = definePluginSettings({
- disableNoisyLoggers: {
+ disableLoggers: {
type: OptionType.BOOLEAN,
- description: "Disable noisy loggers like the MessageActionCreators",
+ description: "Disables Discords loggers",
default: false,
restartNeeded: true
},
@@ -34,16 +36,34 @@ const settings = definePluginSettings({
description: "Disable the Spotify logger, which leaks account information and access token",
default: true,
restartNeeded: true
+ },
+ whitelistedLoggers: {
+ type: OptionType.STRING,
+ description: "Semi colon separated list of loggers to allow even if others are hidden",
+ default: "GatewaySocket; Routing/Utils",
+ onChange(newVal: string) {
+ logAllow.clear();
+ newVal.split(";").map(x => x.trim()).forEach(logAllow.add.bind(logAllow));
+ }
}
});
export default definePlugin({
name: "ConsoleJanitor",
description: "Disables annoying console messages/errors",
- authors: [Devs.Nuckyz],
+ authors: [Devs.Nuckyz, Devs.sadan],
settings,
+ startAt: StartAt.Init,
+ start() {
+ logAllow.clear();
+ this.settings.store.whitelistedLoggers?.split(";").map(x => x.trim()).forEach(logAllow.add.bind(logAllow));
+ },
+
NoopLogger: () => NoopLogger,
+ shouldLog(logger: string) {
+ return logAllow.has(logger);
+ },
patches: [
{
@@ -103,34 +123,13 @@ export default definePlugin({
replace: ""
}
},
- ...[
- '("MessageActionCreators")', '("ChannelMessages")',
- '("Routing/Utils")', '("RTCControlSocket")',
- '("ConnectionEventFramerateReducer")', '("RTCLatencyTestManager")',
- '("OverlayBridgeStore")', '("RPCServer:WSS")', '("RPCServer:IPC")'
- ].map(logger => ({
- find: logger,
- predicate: () => settings.store.disableNoisyLoggers,
- all: true,
- replacement: {
- match: new RegExp(String.raw`new \i\.\i${logger.replace(/([()])/g, "\\$1")}`),
- replace: `$self.NoopLogger${logger}`
- }
- })),
+ // Patches discords generic logger function
{
- find: '"Experimental codecs: "',
- predicate: () => settings.store.disableNoisyLoggers,
+ find: "Σ:",
+ predicate: () => settings.store.disableLoggers,
replacement: {
- match: /new \i\.\i\("Connection\("\.concat\(\i,"\)"\)\)/,
- replace: "$self.NoopLogger()"
- }
- },
- {
- find: '"_handleLocalVideoDisabled: ',
- predicate: () => settings.store.disableNoisyLoggers,
- replacement: {
- match: /new \i\.\i\("RTCConnection\("\.concat.+?\)\)(?=,)/,
- replace: "$self.NoopLogger()"
+ match: /(?<=&&)(?=console)/,
+ replace: "$self.shouldLog(arguments[0])&&"
}
},
{
@@ -141,5 +140,5 @@ export default definePlugin({
replace: "$self.NoopLogger()"
}
}
- ]
+ ],
});
From db5fe2a39472275d2422035d3c55cb6f8cf15538 Mon Sep 17 00:00:00 2001
From: TheGreenPig <67547385+TheGreenPig@users.noreply.github.com>
Date: Sun, 22 Sep 2024 09:38:32 +0200
Subject: [PATCH 08/18] Fix plugin settings inconsistency regarding setting
names (#2884)
---
.../PluginSettings/components/SettingNumericComponent.tsx | 5 ++++-
.../PluginSettings/components/SettingSelectComponent.tsx | 5 ++++-
.../PluginSettings/components/SettingSliderComponent.tsx | 5 ++++-
.../PluginSettings/components/SettingTextComponent.tsx | 5 ++++-
4 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/src/components/PluginSettings/components/SettingNumericComponent.tsx b/src/components/PluginSettings/components/SettingNumericComponent.tsx
index 446d2504..b724717d 100644
--- a/src/components/PluginSettings/components/SettingNumericComponent.tsx
+++ b/src/components/PluginSettings/components/SettingNumericComponent.tsx
@@ -16,6 +16,8 @@
* along with this program. If not, see .
*/
+import { Margins } from "@utils/margins";
+import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { OptionType, PluginOptionNumber } from "@utils/types";
import { Forms, React, TextInput } from "@webpack/common";
@@ -54,7 +56,8 @@ export function SettingNumericComponent({ option, pluginSettings, definedSetting
return (
- {option.description}
+ {wordsToTitle(wordsFromCamel(id))}
+ {option.description}
.
*/
+import { Margins } from "@utils/margins";
+import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionSelect } from "@utils/types";
import { Forms, React, Select } from "@webpack/common";
@@ -44,7 +46,8 @@ export function SettingSelectComponent({ option, pluginSettings, definedSettings
return (
- {option.description}
+ {wordsToTitle(wordsFromCamel(id))}
+ {option.description}
.
*/
+import { Margins } from "@utils/margins";
+import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionSlider } from "@utils/types";
import { Forms, React, Slider } from "@webpack/common";
@@ -50,7 +52,8 @@ export function SettingSliderComponent({ option, pluginSettings, definedSettings
return (
- {option.description}
+ {wordsToTitle(wordsFromCamel(id))}
+ {option.description}
.
*/
+import { Margins } from "@utils/margins";
+import { wordsFromCamel, wordsToTitle } from "@utils/text";
import { PluginOptionString } from "@utils/types";
import { Forms, React, TextInput } from "@webpack/common";
@@ -41,7 +43,8 @@ export function SettingTextComponent({ option, pluginSettings, definedSettings,
return (
- {option.description}
+ {wordsToTitle(wordsFromCamel(id))}
+ {option.description}
Date: Sun, 22 Sep 2024 12:47:18 -0300
Subject: [PATCH 09/18] PronounDB: Rework API to avoid rate limits
---
src/plugins/pronoundb/api.ts | 167 +++++++++++++++++
.../components/PronounsChatComponent.tsx | 30 ++--
src/plugins/pronoundb/index.ts | 8 +-
src/plugins/pronoundb/pronoundbUtils.ts | 169 ------------------
src/plugins/pronoundb/settings.ts | 2 +-
src/plugins/pronoundb/types.ts | 37 ++--
6 files changed, 208 insertions(+), 205 deletions(-)
create mode 100644 src/plugins/pronoundb/api.ts
delete mode 100644 src/plugins/pronoundb/pronoundbUtils.ts
diff --git a/src/plugins/pronoundb/api.ts b/src/plugins/pronoundb/api.ts
new file mode 100644
index 00000000..da2bc651
--- /dev/null
+++ b/src/plugins/pronoundb/api.ts
@@ -0,0 +1,167 @@
+/*
+ * 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 { getCurrentChannel } from "@utils/discord";
+import { useAwaiter } from "@utils/react";
+import { findStoreLazy } from "@webpack";
+import { UserProfileStore } from "@webpack/common";
+
+import { settings } from "./settings";
+import { PronounMapping, Pronouns, PronounsCache, PronounSets, PronounsFormat, PronounSource, PronounsResponse } from "./types";
+
+const UserSettingsAccountStore = findStoreLazy("UserSettingsAccountStore");
+
+const EmptyPronouns = { pronouns: undefined, source: "", hasPendingPronouns: false } as const satisfies Pronouns;
+
+type RequestCallback = (pronounSets?: PronounSets) => void;
+
+const pronounCache: Record = {};
+const requestQueue: Record = {};
+let isProcessing = false;
+
+async function processQueue() {
+ if (isProcessing) return;
+ isProcessing = true;
+
+ let ids = Object.keys(requestQueue);
+ while (ids.length > 0) {
+ const idsChunk = ids.splice(0, 50);
+ const pronouns = await bulkFetchPronouns(idsChunk);
+
+ for (const id of idsChunk) {
+ const callbacks = requestQueue[id];
+ for (const callback of callbacks) {
+ callback(pronouns[id]?.sets);
+ }
+
+ delete requestQueue[id];
+ }
+
+ ids = Object.keys(requestQueue);
+ await new Promise(r => setTimeout(r, 2000));
+ }
+
+ isProcessing = false;
+}
+
+function fetchPronouns(id: string): Promise {
+ return new Promise(resolve => {
+ if (pronounCache[id] != null) {
+ resolve(extractPronouns(pronounCache[id].sets));
+ return;
+ }
+
+ function handlePronouns(pronounSets?: PronounSets) {
+ const pronouns = extractPronouns(pronounSets);
+ resolve(pronouns);
+ }
+
+ if (requestQueue[id] != null) {
+ requestQueue[id].push(handlePronouns);
+ return;
+ }
+
+ requestQueue[id] = [handlePronouns];
+ processQueue();
+ });
+}
+
+async function bulkFetchPronouns(ids: string[]): Promise {
+ const params = new URLSearchParams();
+ params.append("platform", "discord");
+ params.append("ids", ids.join(","));
+
+ try {
+ const req = await fetch("https://pronoundb.org/api/v2/lookup?" + String(params), {
+ method: "GET",
+ headers: {
+ "Accept": "application/json",
+ "X-PronounDB-Source": "WebExtension/0.14.5"
+ }
+ });
+
+ if (!req.ok) throw new Error(`Status ${req.status}`);
+ const res: PronounsResponse = await req.json();
+
+ Object.assign(pronounCache, res);
+ return res;
+
+ } catch (e) {
+ console.error("PronounDB request failed:", e);
+ const dummyPronouns: PronounsResponse = Object.fromEntries(ids.map(id => [id, { sets: {} }]));
+
+ Object.assign(pronounCache, dummyPronouns);
+ return dummyPronouns;
+ }
+}
+
+function extractPronouns(pronounSets?: PronounSets): string | undefined {
+ if (pronounSets == null) return undefined;
+ if (pronounSets.en == null) return PronounMapping.unspecified;
+
+ const pronouns = pronounSets.en;
+ if (pronouns.length === 0) return PronounMapping.unspecified;
+
+ const { pronounsFormat } = settings.store;
+
+ if (pronouns.length > 1) {
+ const pronounString = pronouns.map(p => p[0].toUpperCase() + p.slice(1)).join("/");
+ return pronounsFormat === PronounsFormat.Capitalized ? pronounString : pronounString.toLowerCase();
+ }
+
+ const pronoun = pronouns[0];
+ // For capitalized pronouns or special codes (any, ask, avoid), we always return the normal (capitalized) string
+ if (pronounsFormat === PronounsFormat.Capitalized || ["any", "ask", "avoid", "other", "unspecified"].includes(pronoun)) {
+ return PronounMapping[pronoun];
+ } else {
+ return PronounMapping[pronoun].toLowerCase();
+ }
+}
+
+function getDiscordPronouns(id: string, useGlobalProfile: boolean = false): string | undefined {
+ const globalPronouns = UserProfileStore.getUserProfile(id)?.pronouns;
+ if (useGlobalProfile) return globalPronouns;
+
+ return UserProfileStore.getGuildMemberProfile(id, getCurrentChannel()?.guild_id)?.pronouns || globalPronouns;
+}
+
+export function useFormattedPronouns(id: string, useGlobalProfile: boolean = false): Pronouns {
+ const discordPronouns = getDiscordPronouns(id, useGlobalProfile)?.trim().replace(/\n+/g, "");
+ const hasPendingPronouns = UserSettingsAccountStore.getPendingPronouns() != null;
+
+ const [pronouns] = useAwaiter(() => fetchPronouns(id));
+
+ if (settings.store.pronounSource === PronounSource.PreferDiscord && discordPronouns) {
+ return { pronouns: discordPronouns, source: "Discord", hasPendingPronouns };
+ }
+
+ if (pronouns != null && pronouns !== PronounMapping.unspecified) {
+ return { pronouns, source: "PronounDB", hasPendingPronouns };
+ }
+
+ return { pronouns: discordPronouns, source: "Discord", hasPendingPronouns };
+}
+
+export function useProfilePronouns(id: string, useGlobalProfile: boolean = false): Pronouns {
+ const pronouns = useFormattedPronouns(id, useGlobalProfile);
+
+ if (!settings.store.showInProfile) return EmptyPronouns;
+ if (!settings.store.showSelf && id === UserProfileStore.getCurrentUser()?.id) return EmptyPronouns;
+
+ return pronouns;
+}
diff --git a/src/plugins/pronoundb/components/PronounsChatComponent.tsx b/src/plugins/pronoundb/components/PronounsChatComponent.tsx
index 64fac18b..46c8a8a1 100644
--- a/src/plugins/pronoundb/components/PronounsChatComponent.tsx
+++ b/src/plugins/pronoundb/components/PronounsChatComponent.tsx
@@ -22,7 +22,7 @@ import { findByPropsLazy } from "@webpack";
import { UserStore } from "@webpack/common";
import { Message } from "discord-types/general";
-import { useFormattedPronouns } from "../pronoundbUtils";
+import { useFormattedPronouns } from "../api";
import { settings } from "../settings";
const styles: Record = findByPropsLazy("timestampInline");
@@ -53,25 +53,21 @@ export const CompactPronounsChatComponentWrapper = ErrorBoundary.wrap(({ message
}, { noop: true });
function PronounsChatComponent({ message }: { message: Message; }) {
- const [result] = useFormattedPronouns(message.author.id);
+ const { pronouns } = useFormattedPronouns(message.author.id);
- return result
- ? (
- • {result}
- )
- : null;
+ return pronouns && (
+ • {pronouns}
+ );
}
export const CompactPronounsChatComponent = ErrorBoundary.wrap(({ message }: { message: Message; }) => {
- const [result] = useFormattedPronouns(message.author.id);
+ const { pronouns } = useFormattedPronouns(message.author.id);
- return result
- ? (
- • {result}
- )
- : null;
+ return pronouns && (
+ • {pronouns}
+ );
}, { noop: true });
diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts
index 7dfa8cb4..511aeb1c 100644
--- a/src/plugins/pronoundb/index.ts
+++ b/src/plugins/pronoundb/index.ts
@@ -21,9 +21,9 @@ import "./styles.css";
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
+import { useProfilePronouns } from "./api";
import PronounsAboutComponent from "./components/PronounsAboutComponent";
import { CompactPronounsChatComponentWrapper, PronounsChatComponentWrapper } from "./components/PronounsChatComponent";
-import { useProfilePronouns } from "./pronoundbUtils";
import { settings } from "./settings";
export default definePlugin({
@@ -53,15 +53,15 @@ export default definePlugin({
replacement: [
{
match: /\.PANEL},/,
- replace: "$&[vcPronoun,vcPronounSource,vcHasPendingPronouns]=$self.useProfilePronouns(arguments[0].user?.id),"
+ replace: "$&{pronouns:vcPronoun,source:vcPronounSource,hasPendingPronouns:vcHasPendingPronouns}=$self.useProfilePronouns(arguments[0].user?.id),"
},
{
match: /text:\i\.\i.Messages.USER_PROFILE_PRONOUNS/,
- replace: '$&+(vcHasPendingPronouns?"":` (${vcPronounSource})`)'
+ replace: '$&+(vcPronoun==null||vcHasPendingPronouns?"":` (${vcPronounSource})`)'
},
{
match: /(\.pronounsText.+?children:)(\i)/,
- replace: "$1vcHasPendingPronouns?$2:vcPronoun"
+ replace: "$1(vcPronoun==null||vcHasPendingPronouns)?$2:vcPronoun"
}
]
}
diff --git a/src/plugins/pronoundb/pronoundbUtils.ts b/src/plugins/pronoundb/pronoundbUtils.ts
deleted file mode 100644
index 991e9031..00000000
--- a/src/plugins/pronoundb/pronoundbUtils.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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 { Settings } from "@api/Settings";
-import { debounce } from "@shared/debounce";
-import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
-import { getCurrentChannel } from "@utils/discord";
-import { useAwaiter } from "@utils/react";
-import { findStoreLazy } from "@webpack";
-import { UserProfileStore, UserStore } from "@webpack/common";
-
-import { settings } from "./settings";
-import { CachePronouns, PronounCode, PronounMapping, PronounsResponse } from "./types";
-
-const UserSettingsAccountStore = findStoreLazy("UserSettingsAccountStore");
-
-type PronounsWithSource = [pronouns: string | null, source: string, hasPendingPronouns: boolean];
-const EmptyPronouns: PronounsWithSource = [null, "", false];
-
-export const enum PronounsFormat {
- Lowercase = "LOWERCASE",
- Capitalized = "CAPITALIZED"
-}
-
-export const enum PronounSource {
- PreferPDB,
- PreferDiscord
-}
-
-// A map of cached pronouns so the same request isn't sent twice
-const cache: Record = {};
-// A map of ids and callbacks that should be triggered on fetch
-const requestQueue: Record void)[]> = {};
-
-// Executes all queued requests and calls their callbacks
-const bulkFetch = debounce(async () => {
- const ids = Object.keys(requestQueue);
- const pronouns = await bulkFetchPronouns(ids);
- for (const id of ids) {
- // Call all callbacks for the id
- requestQueue[id]?.forEach(c => c(pronouns[id] ? extractPronouns(pronouns[id].sets) : ""));
- delete requestQueue[id];
- }
-});
-
-function getDiscordPronouns(id: string, useGlobalProfile: boolean = false) {
- const globalPronouns = UserProfileStore.getUserProfile(id)?.pronouns;
-
- if (useGlobalProfile) return globalPronouns;
-
- return (
- UserProfileStore.getGuildMemberProfile(id, getCurrentChannel()?.guild_id)?.pronouns
- || globalPronouns
- );
-}
-
-export function useFormattedPronouns(id: string, useGlobalProfile: boolean = false): PronounsWithSource {
- // Discord is so stupid you can put tons of newlines in pronouns
- const discordPronouns = getDiscordPronouns(id, useGlobalProfile)?.trim().replace(NewLineRe, " ");
-
- const [result] = useAwaiter(() => fetchPronouns(id), {
- fallbackValue: getCachedPronouns(id),
- onError: e => console.error("Fetching pronouns failed: ", e)
- });
-
- const hasPendingPronouns = UserSettingsAccountStore.getPendingPronouns() != null;
-
- if (settings.store.pronounSource === PronounSource.PreferDiscord && discordPronouns)
- return [discordPronouns, "Discord", hasPendingPronouns];
-
- if (result && result !== PronounMapping.unspecified)
- return [result, "PronounDB", hasPendingPronouns];
-
- return [discordPronouns, "Discord", hasPendingPronouns];
-}
-
-export function useProfilePronouns(id: string, useGlobalProfile: boolean = false): PronounsWithSource {
- const pronouns = useFormattedPronouns(id, useGlobalProfile);
-
- if (!settings.store.showInProfile) return EmptyPronouns;
- if (!settings.store.showSelf && id === UserStore.getCurrentUser().id) return EmptyPronouns;
-
- return pronouns;
-}
-
-
-const NewLineRe = /\n+/g;
-
-// Gets the cached pronouns, if you're too impatient for a promise!
-export function getCachedPronouns(id: string): string | null {
- const cached = cache[id] ? extractPronouns(cache[id].sets) : undefined;
-
- if (cached && cached !== PronounMapping.unspecified) return cached;
-
- return cached || null;
-}
-
-// Fetches the pronouns for one id, returning a promise that resolves if it was cached, or once the request is completed
-export function fetchPronouns(id: string): Promise {
- return new Promise(res => {
- const cached = getCachedPronouns(id);
- if (cached) return res(cached);
-
- // If there is already a request added, then just add this callback to it
- if (id in requestQueue) return requestQueue[id].push(res);
-
- // If not already added, then add it and call the debounced function to make sure the request gets executed
- requestQueue[id] = [res];
- bulkFetch();
- });
-}
-
-async function bulkFetchPronouns(ids: string[]): Promise {
- const params = new URLSearchParams();
- params.append("platform", "discord");
- params.append("ids", ids.join(","));
-
- try {
- const req = await fetch("https://pronoundb.org/api/v2/lookup?" + params.toString(), {
- method: "GET",
- headers: {
- "Accept": "application/json",
- "X-PronounDB-Source": VENCORD_USER_AGENT
- }
- });
- return await req.json()
- .then((res: PronounsResponse) => {
- Object.assign(cache, res);
- return res;
- });
- } catch (e) {
- // If the request errors, treat it as if no pronouns were found for all ids, and log it
- console.error("PronounDB fetching failed: ", e);
- const dummyPronouns = Object.fromEntries(ids.map(id => [id, { sets: {} }] as const));
- Object.assign(cache, dummyPronouns);
- return dummyPronouns;
- }
-}
-
-export function extractPronouns(pronounSet?: { [locale: string]: PronounCode[]; }): string {
- if (!pronounSet || !pronounSet.en) return PronounMapping.unspecified;
- // PronounDB returns an empty set instead of {sets: {en: ["unspecified"]}}.
- const pronouns = pronounSet.en;
- const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat, enabled: boolean; };
-
- if (pronouns.length === 1) {
- // For capitalized pronouns or special codes (any, ask, avoid), we always return the normal (capitalized) string
- if (pronounsFormat === PronounsFormat.Capitalized || ["any", "ask", "avoid", "other", "unspecified"].includes(pronouns[0]))
- return PronounMapping[pronouns[0]];
- else return PronounMapping[pronouns[0]].toLowerCase();
- }
- const pronounString = pronouns.map(p => p[0].toUpperCase() + p.slice(1)).join("/");
- return pronounsFormat === PronounsFormat.Capitalized ? pronounString : pronounString.toLowerCase();
-}
diff --git a/src/plugins/pronoundb/settings.ts b/src/plugins/pronoundb/settings.ts
index 5d227978..ebacfbc8 100644
--- a/src/plugins/pronoundb/settings.ts
+++ b/src/plugins/pronoundb/settings.ts
@@ -19,7 +19,7 @@
import { definePluginSettings } from "@api/Settings";
import { OptionType } from "@utils/types";
-import { PronounsFormat, PronounSource } from "./pronoundbUtils";
+import { PronounsFormat, PronounSource } from "./types";
export const settings = definePluginSettings({
pronounsFormat: {
diff --git a/src/plugins/pronoundb/types.ts b/src/plugins/pronoundb/types.ts
index d099a7de..66bb13f0 100644
--- a/src/plugins/pronoundb/types.ts
+++ b/src/plugins/pronoundb/types.ts
@@ -25,22 +25,13 @@ export interface UserProfilePronounsProps {
hidePersonalInformation: boolean;
}
-export interface PronounsResponse {
- [id: string]: {
- sets?: {
- [locale: string]: PronounCode[];
- }
- }
-}
+export type PronounSets = Record;
+export type PronounsResponse = Record;
-export interface CachePronouns {
- sets?: {
- [locale: string]: PronounCode[];
- }
+export interface PronounsCache {
+ sets?: PronounSets;
}
-export type PronounCode = keyof typeof PronounMapping;
-
export const PronounMapping = {
he: "He/Him",
it: "It/Its",
@@ -51,4 +42,22 @@ export const PronounMapping = {
ask: "Ask me my pronouns",
avoid: "Avoid pronouns, use my name",
unspecified: "No pronouns specified.",
-} as const;
+} as const satisfies Record;
+
+export type PronounCode = keyof typeof PronounMapping;
+
+export interface Pronouns {
+ pronouns?: string;
+ source: string;
+ hasPendingPronouns: boolean;
+}
+
+export const enum PronounsFormat {
+ Lowercase = "LOWERCASE",
+ Capitalized = "CAPITALIZED"
+}
+
+export const enum PronounSource {
+ PreferPDB,
+ PreferDiscord
+}
From 65069c673c4bc5a2c14bbba1792bf79a0861750b Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Sun, 22 Sep 2024 13:05:08 -0300
Subject: [PATCH 10/18] UserVoiceShow: Fix showing hidden channels
---
src/plugins/userVoiceShow/components.tsx | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx
index f9a81c4b..c509f694 100644
--- a/src/plugins/userVoiceShow/components.tsx
+++ b/src/plugins/userVoiceShow/components.tsx
@@ -145,6 +145,8 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndi
if (channel == null) return null;
const isDM = channel.isDM() || channel.isMultiUserDM();
+ if (!isDM && !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) && !Vencord.Plugins.isPluginEnabled("ShowHiddenChannels")) return null;
+
const isLocked = !isDM && (!PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel) || !PermissionStore.can(PermissionsBits.CONNECT, channel));
function onClick(e: React.MouseEvent) {
@@ -153,11 +155,6 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndi
if (channel == null || channelId == null) return;
- if (!isDM && !PermissionStore.can(PermissionsBits.VIEW_CHANNEL, channel)) {
- showToast("You cannot view the user's Voice Channel", Toasts.Type.FAILURE);
- return;
- }
-
clearTimeout(clickTimers[channelId]);
delete clickTimers[channelId];
From b0e2f310bc2cd18bae669c7c2c07fc8fdf332774 Mon Sep 17 00:00:00 2001
From: Vendicated
Date: Sun, 22 Sep 2024 18:26:10 +0200
Subject: [PATCH 11/18] RoleColorEverywhere: add chat message colour toggle
---
src/plugins/roleColorEverywhere/index.tsx | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx
index e3b22fd6..c9ededc5 100644
--- a/src/plugins/roleColorEverywhere/index.tsx
+++ b/src/plugins/roleColorEverywhere/index.tsx
@@ -51,13 +51,18 @@ const settings = definePluginSettings({
description: "Show role colors in the reactors list",
restartNeeded: true
},
+ colorChatMessages: {
+ type: OptionType.BOOLEAN,
+ default: false,
+ description: "Color chat messages based on the author's role color",
+ restartNeeded: true,
+ },
messageSaturation: {
type: OptionType.SLIDER,
- description: "Intensity of message coloring. 0 to disable.",
+ description: "Intensity of message coloring.",
markers: makeRange(0, 100, 10),
default: 30,
- // This is called only once at startup, but late enough that the store is initialized.
- get restartNeeded() { return settings.store.messageSaturation === 0; }
+ restartNeeded: true
},
});
@@ -133,7 +138,7 @@ export default definePlugin({
match: /(?<=isUnsupported\]:(\i)\.isUnsupported\}\),)(?=children:\[)/,
replace: "style:{color:$self.useMessageColor($1)},"
},
- predicate: () => settings.store.messageSaturation !== 0,
+ predicate: () => settings.store.colorChatMessages,
},
],
settings,
@@ -176,7 +181,7 @@ export default definePlugin({
const author = useMessageAuthor(message);
if (author.colorString !== undefined && messageSaturation !== 0)
return `color-mix(in oklab, ${author.colorString} ${messageSaturation}%, var(--text-normal))`;
- } catch(e) {
+ } catch (e) {
console.error("[RCE] failed to get message color", e);
}
return undefined;
From 409f47bf2441b24ceac8fc0f2388490e1b10d69d Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Sun, 22 Sep 2024 14:26:50 -0300
Subject: [PATCH 12/18] PronounDB: Fix crashing
---
src/plugins/pronoundb/api.ts | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/plugins/pronoundb/api.ts b/src/plugins/pronoundb/api.ts
index da2bc651..22821796 100644
--- a/src/plugins/pronoundb/api.ts
+++ b/src/plugins/pronoundb/api.ts
@@ -19,7 +19,7 @@
import { getCurrentChannel } from "@utils/discord";
import { useAwaiter } from "@utils/react";
import { findStoreLazy } from "@webpack";
-import { UserProfileStore } from "@webpack/common";
+import { UserProfileStore, UserStore } from "@webpack/common";
import { settings } from "./settings";
import { PronounMapping, Pronouns, PronounsCache, PronounSets, PronounsFormat, PronounSource, PronounsResponse } from "./types";
@@ -158,10 +158,15 @@ export function useFormattedPronouns(id: string, useGlobalProfile: boolean = fal
}
export function useProfilePronouns(id: string, useGlobalProfile: boolean = false): Pronouns {
- const pronouns = useFormattedPronouns(id, useGlobalProfile);
+ try {
+ const pronouns = useFormattedPronouns(id, useGlobalProfile);
- if (!settings.store.showInProfile) return EmptyPronouns;
- if (!settings.store.showSelf && id === UserProfileStore.getCurrentUser()?.id) return EmptyPronouns;
+ if (!settings.store.showInProfile) return EmptyPronouns;
+ if (!settings.store.showSelf && id === UserStore.getCurrentUser()?.id) return EmptyPronouns;
- return pronouns;
+ return pronouns;
+ } catch (e) {
+ console.error(e);
+ return EmptyPronouns;
+ }
}
From c29362ca8972017ad4074586a3bc061a1f79e71b Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Sun, 22 Sep 2024 15:52:25 -0300
Subject: [PATCH 13/18] FullSearchContext: Re-add Copy Author ID
---
src/api/ContextMenu.ts | 11 ++++----
src/plugins/fullSearchContext/index.tsx | 35 ++++++++++++++++++++++---
2 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/src/api/ContextMenu.ts b/src/api/ContextMenu.ts
index fdd4facf..fd8c7e10 100644
--- a/src/api/ContextMenu.ts
+++ b/src/api/ContextMenu.ts
@@ -90,19 +90,20 @@ export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallba
* A helper function for finding the children array of a group nested inside a context menu based on the id(s) of its children
* @param id The id of the child. If an array is specified, all ids will be tried
* @param children The context menu children
+ * @param matchSubstring Whether to check if the id is a substring of the child id
*/
-export function findGroupChildrenByChildId(id: string | string[], children: Array): Array | null {
+export function findGroupChildrenByChildId(id: string | string[], children: Array, matchSubstring = false): Array | null {
for (const child of children) {
if (child == null) continue;
if (Array.isArray(child)) {
- const found = findGroupChildrenByChildId(id, child);
+ const found = findGroupChildrenByChildId(id, child, matchSubstring);
if (found !== null) return found;
}
if (
- (Array.isArray(id) && id.some(id => child.props?.id === id))
- || child.props?.id === id
+ (Array.isArray(id) && id.some(id => matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id))
+ || matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id
) return children;
let nextChildren = child.props?.children;
@@ -112,7 +113,7 @@ export function findGroupChildrenByChildId(id: string | string[], children: Arra
child.props.children = nextChildren;
}
- const found = findGroupChildrenByChildId(id, nextChildren);
+ const found = findGroupChildrenByChildId(id, nextChildren, matchSubstring);
if (found !== null) return found;
}
}
diff --git a/src/plugins/fullSearchContext/index.tsx b/src/plugins/fullSearchContext/index.tsx
index 158612c6..193e69f1 100644
--- a/src/plugins/fullSearchContext/index.tsx
+++ b/src/plugins/fullSearchContext/index.tsx
@@ -16,16 +16,25 @@
* along with this program. If not, see .
*/
+import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
import { migratePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
+import { NoopComponent } from "@utils/react";
import definePlugin from "@utils/types";
-import { findByPropsLazy } from "@webpack";
+import { filters, findByPropsLazy, waitFor } from "@webpack";
import { ChannelStore, ContextMenuApi, i18n, UserStore } from "@webpack/common";
import { Message } from "discord-types/general";
-import type { MouseEvent } from "react";
const { useMessageMenu } = findByPropsLazy("useMessageMenu");
+interface CopyIdMenuItemProps {
+ id: string;
+ label: string;
+}
+
+let CopyIdMenuItem: (props: CopyIdMenuItemProps) => React.ReactElement | null = NoopComponent;
+waitFor(filters.componentByCode('"devmode-copy-id-".concat'), m => CopyIdMenuItem = m);
+
function MessageMenu({ message, channel, onHeightUpdate }) {
const canReport = message.author &&
!(message.author.id === UserStore.getCurrentUser().id || message.author.system);
@@ -48,9 +57,25 @@ function MessageMenu({ message, channel, onHeightUpdate }) {
itemSrc: void 0,
itemSafeSrc: void 0,
itemTextContent: void 0,
+
+ isFullSearchContextMenu: true
});
}
+interface MessageActionsProps {
+ message: Message;
+ isFullSearchContextMenu?: boolean;
+}
+
+const contextMenuPatch: NavContextMenuPatchCallback = (children, props: MessageActionsProps) => {
+ if (props?.isFullSearchContextMenu == null) return;
+
+ const group = findGroupChildrenByChildId("devmode-copy-id", children, true);
+ group?.push(
+ CopyIdMenuItem({ id: props.message.author.id, label: i18n.Messages.COPY_ID_AUTHOR })
+ );
+};
+
migratePluginSettings("FullSearchContext", "SearchReply");
export default definePlugin({
name: "FullSearchContext",
@@ -65,7 +90,7 @@ export default definePlugin({
}
}],
- handleContextMenu(event: MouseEvent, message: Message) {
+ handleContextMenu(event: React.MouseEvent, message: Message) {
const channel = ChannelStore.getChannel(message.channel_id);
if (!channel) return;
@@ -78,5 +103,9 @@ export default definePlugin({
onHeightUpdate={contextMenuProps.onHeightUpdate}
/>
);
+ },
+
+ contextMenus: {
+ "message-actions": contextMenuPatch
}
});
From d7cbe270e56773997c825513712b899b29bda214 Mon Sep 17 00:00:00 2001
From: sadan4 <117494111+sadan4@users.noreply.github.com>
Date: Mon, 23 Sep 2024 02:07:01 -0400
Subject: [PATCH 14/18] FakeNitro: Fix wrongfully allowed emojis in voice calls
(#2901)
---
src/plugins/fakeNitro/index.tsx | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx
index efc19495..2a7a0ee7 100644
--- a/src/plugins/fakeNitro/index.tsx
+++ b/src/plugins/fakeNitro/index.tsx
@@ -203,6 +203,15 @@ export default definePlugin({
settings,
patches: [
+ // Patch the emoji picker in voice calls to not be bypassed by fake nitro
+ {
+ find: "emojiItemDisabled]",
+ predicate: () => settings.store.enableEmojiBypass,
+ replacement: {
+ match: /CHAT/,
+ replace: "STATUS"
+ }
+ },
{
find: ".PREMIUM_LOCKED;",
group: true,
From 5881716c573c09657d8028e55a4cd04dead24582 Mon Sep 17 00:00:00 2001
From: lewisakura
Date: Mon, 23 Sep 2024 07:11:34 +0100
Subject: [PATCH 15/18] RoleColorEverywhere: Fix unneeded restart on setting
change (#2899)
---
src/plugins/roleColorEverywhere/index.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx
index c9ededc5..108ed00c 100644
--- a/src/plugins/roleColorEverywhere/index.tsx
+++ b/src/plugins/roleColorEverywhere/index.tsx
@@ -61,8 +61,7 @@ const settings = definePluginSettings({
type: OptionType.SLIDER,
description: "Intensity of message coloring.",
markers: makeRange(0, 100, 10),
- default: 30,
- restartNeeded: true
+ default: 30
},
});
From eb63a54fa64669981c8be4beab81e5a3c478352f Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Mon, 23 Sep 2024 13:07:19 -0300
Subject: [PATCH 16/18] UserVoiceShow: Fix incorrect dependencies
---
src/plugins/userVoiceShow/index.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx
index 98386a16..07b18c27 100644
--- a/src/plugins/userVoiceShow/index.tsx
+++ b/src/plugins/userVoiceShow/index.tsx
@@ -51,6 +51,7 @@ export default definePlugin({
name: "UserVoiceShow",
description: "Shows an indicator when a user is in a Voice Channel",
authors: [Devs.Nuckyz, Devs.LordElias],
+ dependencies: ["MemberListDecoratorsAPI", "MessageDecorationsAPI"],
settings,
patches: [
From c3f2e76b9cc5deb6c76128bfe52cf0bfb099b282 Mon Sep 17 00:00:00 2001
From: sadan4 <117494111+sadan4@users.noreply.github.com>
Date: Tue, 24 Sep 2024 01:09:33 -0400
Subject: [PATCH 17/18] BetterFolders: Fix sidebar in wrong location (#2904)
---
src/plugins/betterFolders/index.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx
index c2969988..bb1a67eb 100644
--- a/src/plugins/betterFolders/index.tsx
+++ b/src/plugins/betterFolders/index.tsx
@@ -200,8 +200,8 @@ export default definePlugin({
predicate: () => settings.store.sidebar,
replacement: {
// Render the Better Folders sidebar
- match: /(?<=({className:\i\.guilds,themeOverride:\i})\))/,
- replace: ",$self.FolderSideBar({...$1})"
+ match: /(container.{0,50}({className:\i\.guilds,themeOverride:\i})\))/,
+ replace: "$1,$self.FolderSideBar({...$2})"
}
},
{
From cb2848f186f3d074d1a3390643aba70fa481eb6b Mon Sep 17 00:00:00 2001
From: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Date: Tue, 24 Sep 2024 02:13:44 -0300
Subject: [PATCH 18/18] ContextMenuAPI: Fix findGroupChildrenByChildId
---
src/api/ContextMenu.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/api/ContextMenu.ts b/src/api/ContextMenu.ts
index fd8c7e10..114942ff 100644
--- a/src/api/ContextMenu.ts
+++ b/src/api/ContextMenu.ts
@@ -103,7 +103,7 @@ export function findGroupChildrenByChildId(id: string | string[], children: Arra
if (
(Array.isArray(id) && id.some(id => matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id))
- || matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id
+ || (matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id)
) return children;
let nextChildren = child.props?.children;