Compare commits
8 commits
main
...
discord-fi
Author | SHA1 | Date | |
---|---|---|---|
|
e95525429c | ||
|
a15efbb4b2 | ||
|
d06789d963 | ||
|
9ddeb2c67d | ||
|
42628f8bf9 | ||
|
bb6d2f3d82 | ||
|
aa64267ddb | ||
|
76002fb2eb |
11 changed files with 131 additions and 60 deletions
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Vencord, a Discord client mod
|
|
||||||
* Copyright (c) 2024 Vendicated and contributors
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Devs } from "@utils/constants";
|
|
||||||
import definePlugin from "@utils/types";
|
|
||||||
|
|
||||||
|
|
||||||
export default definePlugin({
|
|
||||||
name: "DynamicImageModalAPI",
|
|
||||||
authors: [Devs.sadan, Devs.Nuckyz],
|
|
||||||
description: "Allows you to omit either width or height when opening an image modal",
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: "SCALE_DOWN:",
|
|
||||||
replacement: {
|
|
||||||
match: /!\(null==(\i)\|\|0===\i\|\|null==(\i)\|\|0===\i\)/,
|
|
||||||
replace: (_, width, height) => `!((null == ${width} || 0 === ${width}) && (null == ${height} || 0 === ${height}))`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
114
src/plugins/_core/discordFixes/index.tsx
Normal file
114
src/plugins/_core/discordFixes/index.tsx
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a Discord client mod
|
||||||
|
* Copyright (c) 2025 Vendicated and contributors
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./styles.css";
|
||||||
|
|
||||||
|
import { classNameFactory } from "@api/Styles";
|
||||||
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { Devs } from "@utils/constants";
|
||||||
|
import { classes } from "@utils/misc";
|
||||||
|
import definePlugin from "@utils/types";
|
||||||
|
import { findByCodeLazy } from "@webpack";
|
||||||
|
import { GuildStore, PermissionsBits, PermissionStore, useEffect } from "@webpack/common";
|
||||||
|
import { PropsWithChildren } from "react";
|
||||||
|
|
||||||
|
const cl = classNameFactory("vc-discord-fixes-");
|
||||||
|
|
||||||
|
const fetchMemberSupplemental = findByCodeLazy('type:"FETCH_GUILD_MEMBER_SUPPLEMENTAL_SUCCESS"');
|
||||||
|
|
||||||
|
type UsernameWrapperProps = PropsWithChildren<Record<string, any> & {
|
||||||
|
className?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
const UsernameWrapper = ErrorBoundary.wrap((props: UsernameWrapperProps) => {
|
||||||
|
return <div {...props} className={classes(cl("username-wrapper"), props.className)} />;
|
||||||
|
}, { noop: true });
|
||||||
|
|
||||||
|
type MemberSupplementalCache = Record<string, number>;
|
||||||
|
let memberSupplementalCache = {};
|
||||||
|
|
||||||
|
function setMemberSupplementalCache(cache: MemberSupplementalCache) {
|
||||||
|
memberSupplementalCache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
function useFetchMemberSupplemental(guildId: string, userId: string) {
|
||||||
|
useEffect(() => {
|
||||||
|
if (!PermissionStore.can(PermissionsBits.MANAGE_GUILD, GuildStore.getGuild(guildId))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this member as unfetched in the member supplemental cache
|
||||||
|
memberSupplementalCache[`${guildId}-${userId}`] ??= 1;
|
||||||
|
fetchMemberSupplemental(guildId, [userId]);
|
||||||
|
}, [guildId, userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "DiscordFixes",
|
||||||
|
description: "Fixes Discord issues required or not for Vencord plugins to work properly",
|
||||||
|
authors: [Devs.Nuckyz],
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
patches: [
|
||||||
|
// Make username wrapper a div instead of a span, to align items to center easier with flex
|
||||||
|
{
|
||||||
|
find: '"Message Username"',
|
||||||
|
replacement: {
|
||||||
|
match: /"span"(?=,{id:)/,
|
||||||
|
replace: "$self.UsernameWrapper"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Make MediaModal use the Discord media component instead of a simple "img" component,
|
||||||
|
// if any of height or width exists and is not 0. Default behavior is to only use the component if both exist.
|
||||||
|
{
|
||||||
|
find: "SCALE_DOWN:",
|
||||||
|
replacement: {
|
||||||
|
match: /!\(null==(\i)\|\|0===\i\|\|null==(\i)\|\|0===\i\)/,
|
||||||
|
replace: (_, width, height) => `!((null==${width}||0===${width})&&(null==${height}||0===${height}))`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Make buttons show up for your own activities
|
||||||
|
{
|
||||||
|
find: ".party?(0",
|
||||||
|
all: true,
|
||||||
|
replacement: {
|
||||||
|
match: /\i\.id===\i\.id\?null:/,
|
||||||
|
replace: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Fixes mod view depending on Members page being loaded to acquire the member highest role
|
||||||
|
{
|
||||||
|
find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}),allowOverflow:",
|
||||||
|
replacement: {
|
||||||
|
match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/,
|
||||||
|
replace: "$1$2arguments[0].member.highestRoleId]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Fix mod view join method depending on loading the member in the Members page
|
||||||
|
{
|
||||||
|
find: ".MANUAL_MEMBER_VERIFICATION]:",
|
||||||
|
replacement: {
|
||||||
|
match: /useEffect\(.{0,50}\.requestMembersById\(.+?\[\i,\i\]\);(?<=userId:(\i),guildId:(\i).+?)/,
|
||||||
|
replace: (m, userId, guildId) => `${m}$self.useFetchMemberSupplemental(${guildId},${userId});`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Fix member supplemental caching code and export cache object to use within the plugin code,
|
||||||
|
// there is no other way around it besides patching again
|
||||||
|
{
|
||||||
|
find: ".MEMBER_SAFETY_SUPPLEMENTAL(",
|
||||||
|
replacement: [
|
||||||
|
{
|
||||||
|
match: /(let (\i)={};)(function \i\(\i,\i\){return \i\+)(\i})/,
|
||||||
|
replace: (_, rest1, cache, rest2, rest3) => `${rest1}$self.setMemberSupplementalCache(${cache});${rest2}"-"+${rest3}`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
UsernameWrapper,
|
||||||
|
setMemberSupplementalCache,
|
||||||
|
useFetchMemberSupplemental
|
||||||
|
});
|
11
src/plugins/_core/discordFixes/styles.css
Normal file
11
src/plugins/_core/discordFixes/styles.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.vc-discord-fixes-username-wrapper {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove top gap from chat tags, because the plugin makes it use a div to center instead */
|
||||||
|
[class*="botTag"][class*="rem"] {
|
||||||
|
margin-top: unset;
|
||||||
|
top: unset;
|
||||||
|
}
|
|
@ -399,17 +399,6 @@ export default definePlugin({
|
||||||
stop: () => setRpc(true),
|
stop: () => setRpc(true),
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: ".party?(0",
|
|
||||||
all: true,
|
|
||||||
replacement: {
|
|
||||||
match: /\i\.id===\i\.id\?null:/,
|
|
||||||
replace: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
settingsAboutComponent: () => {
|
settingsAboutComponent: () => {
|
||||||
const activity = useAwaiter(createActivity);
|
const activity = useAwaiter(createActivity);
|
||||||
const gameActivityEnabled = ShowCurrentGame.useSetting();
|
const gameActivityEnabled = ShowCurrentGame.useSetting();
|
||||||
|
|
|
@ -133,7 +133,7 @@ function getBadges({ userId }: BadgeUserArgs): ProfileBadge[] {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, small = false }: { user: User; wantMargin?: boolean; wantTopMargin?: boolean; small?: boolean; }) => {
|
const PlatformIndicator = ({ user, wantMargin = true, small = false }: { user: User; wantMargin?: boolean; small?: boolean; }) => {
|
||||||
if (!user || user.bot) return null;
|
if (!user || user.bot) return null;
|
||||||
|
|
||||||
ensureOwnStatus(user);
|
ensureOwnStatus(user);
|
||||||
|
@ -157,7 +157,6 @@ const PlatformIndicator = ({ user, wantMargin = true, wantTopMargin = false, sma
|
||||||
className="vc-platform-indicator"
|
className="vc-platform-indicator"
|
||||||
style={{
|
style={{
|
||||||
marginLeft: wantMargin ? 4 : 0,
|
marginLeft: wantMargin ? 4 : 0,
|
||||||
top: wantTopMargin ? 2 : 0,
|
|
||||||
gap: 2
|
gap: 2
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -190,7 +189,7 @@ const indicatorLocations = {
|
||||||
description: "Inside messages",
|
description: "Inside messages",
|
||||||
onEnable: () => addMessageDecoration("platform-indicator", props =>
|
onEnable: () => addMessageDecoration("platform-indicator", props =>
|
||||||
<ErrorBoundary noop>
|
<ErrorBoundary noop>
|
||||||
<PlatformIndicator user={props.message?.author} wantTopMargin={true} />
|
<PlatformIndicator user={props.message?.author} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
),
|
),
|
||||||
onDisable: () => removeMessageDecoration("platform-indicator")
|
onDisable: () => removeMessageDecoration("platform-indicator")
|
||||||
|
|
|
@ -28,7 +28,6 @@ export default definePlugin({
|
||||||
name: "ServerInfo",
|
name: "ServerInfo",
|
||||||
description: "Allows you to view info about a server",
|
description: "Allows you to view info about a server",
|
||||||
authors: [Devs.Ven, Devs.Nuckyz],
|
authors: [Devs.Ven, Devs.Nuckyz],
|
||||||
dependencies: ["DynamicImageModalAPI"],
|
|
||||||
tags: ["guild", "info", "ServerProfile"],
|
tags: ["guild", "info", "ServerProfile"],
|
||||||
|
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
|
|
|
@ -65,16 +65,7 @@ export default definePlugin({
|
||||||
replace: "return true",
|
replace: "return true",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// fixes a bug where Members page must be loaded to see highest role, why is Discord depending on MemberSafetyStore.getEnhancedMember for something that can be obtained here?
|
// Allows you to open mod view on yourself
|
||||||
{
|
|
||||||
find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}),allowOverflow:",
|
|
||||||
predicate: () => settings.store.showModView,
|
|
||||||
replacement: {
|
|
||||||
match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/,
|
|
||||||
replace: "$1$2arguments[0].member.highestRoleId]",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// allows you to open mod view on yourself
|
|
||||||
{
|
{
|
||||||
find: 'action:"PRESS_MOD_VIEW",icon:',
|
find: 'action:"PRESS_MOD_VIEW",icon:',
|
||||||
predicate: () => settings.store.showModView,
|
predicate: () => settings.store.showModView,
|
||||||
|
|
|
@ -130,7 +130,6 @@ function VoiceChannelTooltip({ channel, isLocked }: VoiceChannelTooltipProps) {
|
||||||
|
|
||||||
interface VoiceChannelIndicatorProps {
|
interface VoiceChannelIndicatorProps {
|
||||||
userId: string;
|
userId: string;
|
||||||
isMessageIndicator?: boolean;
|
|
||||||
isProfile?: boolean;
|
isProfile?: boolean;
|
||||||
isActionButton?: boolean;
|
isActionButton?: boolean;
|
||||||
shouldHighlight?: boolean;
|
shouldHighlight?: boolean;
|
||||||
|
@ -138,7 +137,7 @@ interface VoiceChannelIndicatorProps {
|
||||||
|
|
||||||
const clickTimers = {} as Record<string, any>;
|
const clickTimers = {} as Record<string, any>;
|
||||||
|
|
||||||
export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndicator, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
|
export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isProfile, isActionButton, shouldHighlight }: VoiceChannelIndicatorProps) => {
|
||||||
const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined);
|
const channelId = useStateFromStores([VoiceStateStore], () => VoiceStateStore.getVoiceStateForUser(userId)?.channelId as string | undefined);
|
||||||
|
|
||||||
const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId);
|
const channel = channelId == null ? undefined : ChannelStore.getChannel(channelId);
|
||||||
|
@ -182,7 +181,7 @@ export const VoiceChannelIndicator = ErrorBoundary.wrap(({ userId, isMessageIndi
|
||||||
{props => {
|
{props => {
|
||||||
const iconProps: IconProps = {
|
const iconProps: IconProps = {
|
||||||
...props,
|
...props,
|
||||||
className: classes(isMessageIndicator && cl("message-indicator"), (!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight),
|
className: classes((!isProfile && !isActionButton) && cl("speaker-margin"), isActionButton && ActionButtonClasses.actionButton, shouldHighlight && ActionButtonClasses.highlight),
|
||||||
size: isActionButton ? 20 : undefined,
|
size: isActionButton ? 20 : undefined,
|
||||||
onClick
|
onClick
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@ export default definePlugin({
|
||||||
addMemberListDecorator("UserVoiceShow", ({ user }) => user == null ? null : <VoiceChannelIndicator userId={user.id} />);
|
addMemberListDecorator("UserVoiceShow", ({ user }) => user == null ? null : <VoiceChannelIndicator userId={user.id} />);
|
||||||
}
|
}
|
||||||
if (settings.store.showInMessages) {
|
if (settings.store.showInMessages) {
|
||||||
addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : <VoiceChannelIndicator userId={message.author.id} isMessageIndicator />);
|
addMessageDecoration("UserVoiceShow", ({ message }) => message?.author == null ? null : <VoiceChannelIndicator userId={message.author.id} />);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,6 @@
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vc-uvs-message-indicator {
|
|
||||||
display: inline-flex;
|
|
||||||
top: 2.5px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vc-uvs-tooltip-container {
|
.vc-uvs-tooltip-container {
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,6 @@ export default definePlugin({
|
||||||
authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz, Devs.nyx],
|
authors: [Devs.Ven, Devs.TheKodeToad, Devs.Nuckyz, Devs.nyx],
|
||||||
description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.",
|
description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.",
|
||||||
tags: ["ImageUtilities"],
|
tags: ["ImageUtilities"],
|
||||||
dependencies: ["DynamicImageModalAPI"],
|
|
||||||
|
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue