Skip to content

Commit e418108

Browse files
committed
Merge branch 'main' of https://github.com/ScyyeCord/Vencord
2 parents ee81439 + 34a0447 commit e418108

File tree

82 files changed

+1255
-803
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1255
-803
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vencord",
33
"private": "true",
4-
"version": "1.10.1",
4+
"version": "1.10.4",
55
"description": "The cutest Discord client mod",
66
"homepage": "https://github.com/Vendicated/Vencord#readme",
77
"bugs": {

src/api/ContextMenu.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,20 @@ export function removeGlobalContextMenuPatch(patch: GlobalContextMenuPatchCallba
9090
* A helper function for finding the children array of a group nested inside a context menu based on the id(s) of its children
9191
* @param id The id of the child. If an array is specified, all ids will be tried
9292
* @param children The context menu children
93+
* @param matchSubstring Whether to check if the id is a substring of the child id
9394
*/
94-
export function findGroupChildrenByChildId(id: string | string[], children: Array<ReactElement | null>): Array<ReactElement | null> | null {
95+
export function findGroupChildrenByChildId(id: string | string[], children: Array<ReactElement | null | undefined>, matchSubstring = false): Array<ReactElement | null | undefined> | null {
9596
for (const child of children) {
9697
if (child == null) continue;
9798

9899
if (Array.isArray(child)) {
99-
const found = findGroupChildrenByChildId(id, child);
100+
const found = findGroupChildrenByChildId(id, child, matchSubstring);
100101
if (found !== null) return found;
101102
}
102103

103104
if (
104-
(Array.isArray(id) && id.some(id => child.props?.id === id))
105-
|| child.props?.id === id
105+
(Array.isArray(id) && id.some(id => matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id))
106+
|| (matchSubstring ? child.props?.id?.includes(id) : child.props?.id === id)
106107
) return children;
107108

108109
let nextChildren = child.props?.children;
@@ -112,7 +113,7 @@ export function findGroupChildrenByChildId(id: string | string[], children: Arra
112113
child.props.children = nextChildren;
113114
}
114115

115-
const found = findGroupChildrenByChildId(id, nextChildren);
116+
const found = findGroupChildrenByChildId(id, nextChildren, matchSubstring);
116117
if (found !== null) return found;
117118
}
118119
}

src/components/PluginSettings/components/SettingNumericComponent.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19+
import { Margins } from "@utils/margins";
20+
import { wordsFromCamel, wordsToTitle } from "@utils/text";
1921
import { OptionType, PluginOptionNumber } from "@utils/types";
2022
import { Forms, React, TextInput } from "@webpack/common";
2123

@@ -54,7 +56,8 @@ export function SettingNumericComponent({ option, pluginSettings, definedSetting
5456

5557
return (
5658
<Forms.FormSection>
57-
<Forms.FormTitle>{option.description}</Forms.FormTitle>
59+
<Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
60+
<Forms.FormText className={Margins.bottom20} type="description">{option.description}</Forms.FormText>
5861
<TextInput
5962
type="number"
6063
pattern="-?[0-9]+"

src/components/PluginSettings/components/SettingSelectComponent.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19+
import { Margins } from "@utils/margins";
20+
import { wordsFromCamel, wordsToTitle } from "@utils/text";
1921
import { PluginOptionSelect } from "@utils/types";
2022
import { Forms, React, Select } from "@webpack/common";
2123

@@ -44,7 +46,8 @@ export function SettingSelectComponent({ option, pluginSettings, definedSettings
4446

4547
return (
4648
<Forms.FormSection>
47-
<Forms.FormTitle>{option.description}</Forms.FormTitle>
49+
<Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
50+
<Forms.FormText className={Margins.bottom16} type="description">{option.description}</Forms.FormText>
4851
<Select
4952
isDisabled={option.disabled?.call(definedSettings) ?? false}
5053
options={option.options}

src/components/PluginSettings/components/SettingSliderComponent.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19+
import { Margins } from "@utils/margins";
20+
import { wordsFromCamel, wordsToTitle } from "@utils/text";
1921
import { PluginOptionSlider } from "@utils/types";
2022
import { Forms, React, Slider } from "@webpack/common";
2123

@@ -50,7 +52,8 @@ export function SettingSliderComponent({ option, pluginSettings, definedSettings
5052

5153
return (
5254
<Forms.FormSection>
53-
<Forms.FormTitle>{option.description}</Forms.FormTitle>
55+
<Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
56+
<Forms.FormText className={Margins.bottom20} type="description">{option.description}</Forms.FormText>
5457
<Slider
5558
disabled={option.disabled?.call(definedSettings) ?? false}
5659
markers={option.markers}

src/components/PluginSettings/components/SettingTextComponent.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19+
import { Margins } from "@utils/margins";
20+
import { wordsFromCamel, wordsToTitle } from "@utils/text";
1921
import { PluginOptionString } from "@utils/types";
2022
import { Forms, React, TextInput } from "@webpack/common";
2123

@@ -41,7 +43,8 @@ export function SettingTextComponent({ option, pluginSettings, definedSettings,
4143

4244
return (
4345
<Forms.FormSection>
44-
<Forms.FormTitle>{option.description}</Forms.FormTitle>
46+
<Forms.FormTitle>{wordsToTitle(wordsFromCamel(id))}</Forms.FormTitle>
47+
<Forms.FormText className={Margins.bottom20} type="description">{option.description}</Forms.FormText>
4548
<TextInput
4649
type="text"
4750
value={state}

src/components/PluginSettings/index.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ interface PluginCardProps extends React.HTMLProps<HTMLDivElement> {
9393
export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLeave, isNew }: PluginCardProps) {
9494
const settings = Settings.plugins[plugin.name];
9595

96-
const isEnabled = () => settings.enabled ?? false;
96+
const isEnabled = () => Vencord.Plugins.isPluginEnabled(plugin.name);
9797

9898
function toggleEnabled() {
9999
const wasEnabled = isEnabled();
@@ -292,10 +292,10 @@ export default function PluginSettings() {
292292

293293
if (!pluginFilter(p)) continue;
294294

295-
const isRequired = p.required || depMap[p.name]?.some(d => settings.plugins[d].enabled);
295+
const isRequired = p.required || p.isDependency || depMap[p.name]?.some(d => settings.plugins[d].enabled);
296296

297297
if (isRequired) {
298-
const tooltipText = p.required
298+
const tooltipText = p.required || !depMap[p.name]
299299
? "This plugin is required for Vencord to function."
300300
: makeDependencyList(depMap[p.name]?.filter(d => settings.plugins[d].enabled));
301301

src/plugins/_core/noTrack.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export default definePlugin({
4848
},
4949
},
5050
{
51-
find: ".METRICS,",
51+
find: ".METRICS",
5252
replacement: [
5353
{
5454
match: /this\._intervalId=/,

src/plugins/_core/supportHelper.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export default definePlugin({
142142
required: true,
143143
description: "Helps us provide support to you",
144144
authors: [Devs.Ven],
145-
dependencies: ["CommandsAPI", "UserSettingsAPI", "MessageAccessoriesAPI"],
145+
dependencies: ["UserSettingsAPI", "MessageAccessoriesAPI"],
146146

147147
settings,
148148

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# AccountPanelServerProfile
2+
3+
Right click your account panel in the bottom left to view your profile in the current server
4+
5+
![](https://github.com/user-attachments/assets/3228497d-488f-479c-93d2-a32ccdb08f0f)
6+
7+
![](https://github.com/user-attachments/assets/6fc45363-d95f-4810-812f-2f9fb28b41b5)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Vencord, a Discord client mod
3+
* Copyright (c) 2024 Vendicated and contributors
4+
* SPDX-License-Identifier: GPL-3.0-or-later
5+
*/
6+
7+
import { definePluginSettings } from "@api/Settings";
8+
import ErrorBoundary from "@components/ErrorBoundary";
9+
import { Devs } from "@utils/constants";
10+
import { getCurrentChannel } from "@utils/discord";
11+
import definePlugin, { OptionType } from "@utils/types";
12+
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
13+
import { ContextMenuApi, Menu, useEffect, useRef } from "@webpack/common";
14+
import { User } from "discord-types/general";
15+
16+
interface UserProfileProps {
17+
popoutProps: Record<string, any>;
18+
currentUser: User;
19+
originalPopout: () => React.ReactNode;
20+
}
21+
22+
const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined");
23+
const styles = findByPropsLazy("accountProfilePopoutWrapper");
24+
25+
let openAlternatePopout = false;
26+
let accountPanelRef: React.MutableRefObject<Record<PropertyKey, any> | null> = { current: null };
27+
28+
const AccountPanelContextMenu = ErrorBoundary.wrap(() => {
29+
const { prioritizeServerProfile } = settings.use(["prioritizeServerProfile"]);
30+
31+
return (
32+
<Menu.Menu
33+
navId="vc-ap-server-profile"
34+
onClose={ContextMenuApi.closeContextMenu}
35+
>
36+
<Menu.MenuItem
37+
id="vc-ap-view-alternate-popout"
38+
label={prioritizeServerProfile ? "View Account Profile" : "View Server Profile"}
39+
disabled={getCurrentChannel()?.getGuildId() == null}
40+
action={e => {
41+
openAlternatePopout = true;
42+
accountPanelRef.current?.props.onMouseDown();
43+
accountPanelRef.current?.props.onClick(e);
44+
}}
45+
/>
46+
<Menu.MenuCheckboxItem
47+
id="vc-ap-prioritize-server-profile"
48+
label="Prioritize Server Profile"
49+
checked={prioritizeServerProfile}
50+
action={() => settings.store.prioritizeServerProfile = !prioritizeServerProfile}
51+
/>
52+
</Menu.Menu>
53+
);
54+
}, { noop: true });
55+
56+
const settings = definePluginSettings({
57+
prioritizeServerProfile: {
58+
type: OptionType.BOOLEAN,
59+
description: "Prioritize Server Profile when left clicking your account panel",
60+
default: false
61+
}
62+
});
63+
64+
export default definePlugin({
65+
name: "AccountPanelServerProfile",
66+
description: "Right click your account panel in the bottom left to view your profile in the current server",
67+
authors: [Devs.Nuckyz, Devs.relitrix],
68+
settings,
69+
70+
patches: [
71+
{
72+
find: ".Messages.ACCOUNT_SPEAKING_WHILE_MUTED",
73+
group: true,
74+
replacement: [
75+
{
76+
match: /(?<=\.SIZE_32\)}\);)/,
77+
replace: "$self.useAccountPanelRef();"
78+
},
79+
{
80+
match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/,
81+
replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalPopout:()=>{${originalPopout}}})`
82+
},
83+
{
84+
match: /\.AVATAR,children:.+?(?=renderPopout:)/,
85+
replace: "$&onRequestClose:$self.onPopoutClose,"
86+
},
87+
{
88+
match: /(?<=.avatarWrapper,)/,
89+
replace: "ref:$self.accountPanelRef,onContextMenu:$self.openAccountPanelContextMenu,"
90+
}
91+
]
92+
}
93+
],
94+
95+
get accountPanelRef() {
96+
return accountPanelRef;
97+
},
98+
99+
useAccountPanelRef() {
100+
useEffect(() => () => {
101+
accountPanelRef.current = null;
102+
}, []);
103+
104+
return (accountPanelRef = useRef(null));
105+
},
106+
107+
openAccountPanelContextMenu(event: React.UIEvent) {
108+
ContextMenuApi.openContextMenu(event, AccountPanelContextMenu);
109+
},
110+
111+
onPopoutClose() {
112+
openAlternatePopout = false;
113+
},
114+
115+
UserProfile: ErrorBoundary.wrap(({ popoutProps, currentUser, originalPopout }: UserProfileProps) => {
116+
if (
117+
(settings.store.prioritizeServerProfile && openAlternatePopout) ||
118+
(!settings.store.prioritizeServerProfile && !openAlternatePopout)
119+
) {
120+
return originalPopout();
121+
}
122+
123+
const currentChannel = getCurrentChannel();
124+
if (currentChannel?.getGuildId() == null) {
125+
return originalPopout();
126+
}
127+
128+
return (
129+
<div className={styles.accountProfilePopoutWrapper}>
130+
<UserProfile {...popoutProps} userId={currentUser.id} guildId={currentChannel.getGuildId()} channelId={currentChannel.id} />
131+
</div>
132+
);
133+
}, { noop: true })
134+
});

src/plugins/anonymiseFileNames/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default definePlugin({
7171
description: "Anonymise uploaded file names",
7272
patches: [
7373
{
74-
find: "instantBatchUpload:function",
74+
find: "instantBatchUpload:",
7575
replacement: {
7676
match: /uploadFiles:(\i),/,
7777
replace:

0 commit comments

Comments
 (0)