;
+
+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
+}
diff --git a/src/plugins/replaceGoogleSearch/index.tsx b/src/plugins/replaceGoogleSearch/index.tsx
index 986534b5..036d8275 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=",
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}),"
diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx
index b5f66c09..c9ededc5 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,26 @@ const settings = definePluginSettings({
default: true,
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.",
+ markers: makeRange(0, 100, 10),
+ default: 30,
+ restartNeeded: true
+ },
});
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 +131,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.colorChatMessages,
+ },
],
settings,
@@ -148,5 +173,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;
+ },
});
diff --git a/src/plugins/userVoiceShow/components.tsx b/src/plugins/userVoiceShow/components.tsx
index f248cf72..a49a1db3 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, isActionButton, isMessageIndicator }: 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);
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) {
@@ -148,11 +155,6 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isActionButto
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];
@@ -165,7 +167,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isActionButto
selectVoiceChannel(channelId);
} else {
clickTimers[channelId] = setTimeout(() => {
- NavigationRouter.transitionTo(`/channels/${channel.getGuildId() ?? "@me"}/${channelId}`);
+ ChannelRouter.transitionToChannel(channelId);
delete clickTimers[channelId];
}, 250);
}
@@ -173,14 +175,14 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isActionButto
return (
}
+ text={}
tooltipClassName={cl("tooltip-container")}
tooltipContentClassName={cl("tooltip-content")}
>
{props => {
const iconProps: IconProps = {
...props,
- 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
};
diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx
index d30c5b7f..98386a16 100644
--- a/src/plugins/userVoiceShow/index.tsx
+++ b/src/plugins/userVoiceShow/index.tsx
@@ -59,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
},
@@ -86,8 +86,8 @@ export default definePlugin({
{
find: "null!=this.peopleListItemRef.current",
replacement: {
- match: /\.actions,children:\[/,
- replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true}),"
+ match: /\.actions,children:\[(?<=isFocused:(\i).+?)/,
+ replace: "$&$self.VoiceChannelIndicator({userId:this?.props?.user?.id,isActionButton:true,shouldHighlight:$1}),"
},
predicate: () => settings.store.showInMemberList
}
diff --git a/src/plugins/userVoiceShow/style.css b/src/plugins/userVoiceShow/style.css
index 072dee94..d172975b 100644
--- a/src/plugins/userVoiceShow/style.css
+++ b/src/plugins/userVoiceShow/style.css
@@ -13,26 +13,16 @@
color: var(--interactive-hover);
}
-.vc-uvs-speaker-padding {
- padding: 0 4px;
+.vc-uvs-speaker-margin {
+ margin-left: 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%;
- height: 36px;
- width: 36px;
- margin-left: 10px;
-}
-
.vc-uvs-tooltip-container {
max-width: 300px;
}
diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts
index 92052a8b..0955e52a 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";
@@ -175,6 +175,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 83805744..5ce401b2 100644
--- a/src/webpack/common/utils.ts
+++ b/src/webpack/common/utils.ts
@@ -151,6 +151,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);