Merge branch 'dev' into discord-fixes
This commit is contained in:
commit
e95525429c
38 changed files with 192 additions and 192 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "vencord",
|
"name": "vencord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.11.2",
|
"version": "1.11.3",
|
||||||
"description": "The cutest Discord client mod",
|
"description": "The cutest Discord client mod",
|
||||||
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import { Constructor } from "type-fest";
|
||||||
import { PluginMeta } from "~plugins";
|
import { PluginMeta } from "~plugins";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
ISettingCustomElementProps,
|
||||||
ISettingElementProps,
|
ISettingElementProps,
|
||||||
SettingBooleanComponent,
|
SettingBooleanComponent,
|
||||||
SettingCustomComponent,
|
SettingCustomComponent,
|
||||||
|
@ -74,7 +75,7 @@ function makeDummyUser(user: { username: string; id?: string; avatar?: string; }
|
||||||
return newUser;
|
return newUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Components: Record<OptionType, React.ComponentType<ISettingElementProps<any>>> = {
|
const Components: Record<OptionType, React.ComponentType<ISettingElementProps<any> | ISettingCustomElementProps<any>>> = {
|
||||||
[OptionType.STRING]: SettingTextComponent,
|
[OptionType.STRING]: SettingTextComponent,
|
||||||
[OptionType.NUMBER]: SettingNumericComponent,
|
[OptionType.NUMBER]: SettingNumericComponent,
|
||||||
[OptionType.BIGINT]: SettingNumericComponent,
|
[OptionType.BIGINT]: SettingNumericComponent,
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
import { PluginOptionComponent } from "@utils/types";
|
import { PluginOptionComponent } from "@utils/types";
|
||||||
|
|
||||||
import { ISettingElementProps } from ".";
|
import { ISettingCustomElementProps } from ".";
|
||||||
|
|
||||||
export function SettingCustomComponent({ option, onChange, onError }: ISettingElementProps<PluginOptionComponent>) {
|
export function SettingCustomComponent({ option, onChange, onError }: ISettingCustomElementProps<PluginOptionComponent>) {
|
||||||
return option.component({ setValue: onChange, setError: onError, option });
|
return option.component({ setValue: onChange, setError: onError, option });
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
import { DefinedSettings, PluginOptionBase } from "@utils/types";
|
import { DefinedSettings, PluginOptionBase } from "@utils/types";
|
||||||
|
|
||||||
export interface ISettingElementProps<T extends PluginOptionBase> {
|
interface ISettingElementPropsBase<T> {
|
||||||
option: T;
|
option: T;
|
||||||
onChange(newValue: any): void;
|
onChange(newValue: any): void;
|
||||||
pluginSettings: {
|
pluginSettings: {
|
||||||
|
@ -30,6 +30,9 @@ export interface ISettingElementProps<T extends PluginOptionBase> {
|
||||||
definedSettings?: DefinedSettings;
|
definedSettings?: DefinedSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ISettingElementProps<T extends PluginOptionBase> = ISettingElementPropsBase<T>;
|
||||||
|
export type ISettingCustomElementProps<T extends Omit<PluginOptionBase, "description" | "placeholder">> = ISettingElementPropsBase<T>;
|
||||||
|
|
||||||
export * from "../../Badge";
|
export * from "../../Badge";
|
||||||
export * from "./SettingBooleanComponent";
|
export * from "./SettingBooleanComponent";
|
||||||
export * from "./SettingCustomComponent";
|
export * from "./SettingCustomComponent";
|
||||||
|
|
|
@ -16,6 +16,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: '"sticker")',
|
find: '"sticker")',
|
||||||
replacement: {
|
replacement: {
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /return\((!)?\i\.\i(?:\|\||&&)(?=\(\i\.isDM.+?(\i)\.push)/,
|
match: /return\((!)?\i\.\i(?:\|\||&&)(?=\(\i\.isDM.+?(\i)\.push)/,
|
||||||
replace: (m, not, children) => not
|
replace: (m, not, children) => not
|
||||||
? `${m}(Vencord.Api.ChatButtons._injectButtons(${children},arguments[0]),true)&&`
|
? `${m}(Vencord.Api.ChatButtons._injectButtons(${children},arguments[0]),true)&&`
|
||||||
|
|
|
@ -37,12 +37,9 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: ".handleSendMessage,onResize",
|
find: ".handleSendMessage,onResize",
|
||||||
replacement: {
|
replacement: {
|
||||||
// props.chatInputType...then((function(isMessageValid)... var parsedMessage = b.c.parse(channel,... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply);
|
// https://regex101.com/r/hBlXpl/1
|
||||||
// Lookbehind: validateMessage)({openWarningPopout:..., type: i.props.chatInputType, content: t, stickers: r, ...}).then((function(isMessageValid)
|
match: /let (\i)=\i\.\i\.parse\((\i),.+?let (\i)=\i\.\i\.getSendMessageOptions\(\{.+?\}\);(?<=\)\(({.+?})\)\.then.+?)/,
|
||||||
match: /(\{openWarningPopout:.{0,100}type:this.props.chatInputType.+?\.then\()(\i=>\{.+?let (\i)=\i\.\i\.parse\((\i),.+?let (\i)=\i\.\i\.getSendMessageOptions\(\{.+?\}\);)(?<=\)\(({.+?})\)\.then.+?)/,
|
replace: (m, parsedMessage, channel, replyOptions, extra) => m +
|
||||||
// props.chatInputType...then((async function(isMessageValid)... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); if(await Vencord.api...) return { shoudClear:true, shouldRefocus:true };
|
|
||||||
replace: (_, rest1, rest2, parsedMessage, channel, replyOptions, extra) => "" +
|
|
||||||
`${rest1}async ${rest2}` +
|
|
||||||
`if(await Vencord.Api.MessageEvents._handlePreSend(${channel}.id,${parsedMessage},${extra},${replyOptions}))` +
|
`if(await Vencord.Api.MessageEvents._handlePreSend(${channel}.id,${parsedMessage},${extra},${replyOptions}))` +
|
||||||
"return{shouldClear:false,shouldRefocus:true};"
|
"return{shouldClear:false,shouldRefocus:true};"
|
||||||
}
|
}
|
||||||
|
@ -52,8 +49,7 @@ export default definePlugin({
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /let\{id:\i}=(\i),{id:\i}=(\i);return \i\.useCallback\((\i)=>\{/,
|
match: /let\{id:\i}=(\i),{id:\i}=(\i);return \i\.useCallback\((\i)=>\{/,
|
||||||
replace: (m, message, channel, event) =>
|
replace: (m, message, channel, event) =>
|
||||||
// the message param is shadowed by the event param, so need to alias them
|
`const vcMsg=${message},vcChan=${channel};${m}Vencord.Api.MessageEvents._handleClick(vcMsg,vcChan,${event});`
|
||||||
`const vcMsg=${message},vcChan=${channel};${m}Vencord.Api.MessageEvents._handleClick(vcMsg, vcChan, ${event});`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -65,6 +65,7 @@ export default definePlugin({
|
||||||
replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}`
|
replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /({(?=.+?function (\i).{0,160}(\i)=\i\.useMemo.{0,140}return \i\.useMemo\(\(\)=>\i\(\3).+?(?:function\(\){return |\(\)=>))\2/,
|
match: /({(?=.+?function (\i).{0,160}(\i)=\i\.useMemo.{0,140}return \i\.useMemo\(\(\)=>\i\(\3).+?(?:function\(\){return |\(\)=>))\2/,
|
||||||
replace: (_, rest, settingsHook) => `${rest}$self.wrapSettingsHook(${settingsHook})`
|
replace: (_, rest, settingsHook) => `${rest}$self.wrapSettingsHook(${settingsHook})`
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ export default definePlugin({
|
||||||
// Status emojis
|
// Status emojis
|
||||||
find: "#{intl::GUILD_OWNER}),children:",
|
find: "#{intl::GUILD_OWNER}),children:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<=\.activityEmoji,.+?animate:)\i/,
|
match: /(\.CUSTOM_STATUS.+?animate:)\i/,
|
||||||
replace: "!0"
|
replace: (_, rest) => `${rest}!0`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,14 +17,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
import { findComponentByCodeLazy, findStoreLazy } from "@webpack";
|
||||||
import { useStateFromStores } from "@webpack/common";
|
import { Animations, useStateFromStores } from "@webpack/common";
|
||||||
import type { CSSProperties } from "react";
|
import type { CSSProperties } from "react";
|
||||||
|
|
||||||
import { ExpandedGuildFolderStore, settings } from ".";
|
import { ExpandedGuildFolderStore, settings } from ".";
|
||||||
|
|
||||||
const ChannelRTCStore = findStoreLazy("ChannelRTCStore");
|
const ChannelRTCStore = findStoreLazy("ChannelRTCStore");
|
||||||
const Animations = findByPropsLazy("a", "animated", "useTransition");
|
|
||||||
const GuildsBar = findComponentByCodeLazy('("guildsnav")');
|
const GuildsBar = findComponentByCodeLazy('("guildsnav")');
|
||||||
|
|
||||||
export default ErrorBoundary.wrap(guildsBarProps => {
|
export default ErrorBoundary.wrap(guildsBarProps => {
|
||||||
|
|
|
@ -91,15 +91,12 @@ function ThemeSettings() {
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
color: {
|
color: {
|
||||||
description: "Color your Discord client theme will be based around. Light mode isn't supported",
|
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
default: "313338",
|
default: "313338",
|
||||||
component: () => <ThemeSettings />
|
component: ThemeSettings
|
||||||
},
|
},
|
||||||
resetColor: {
|
resetColor: {
|
||||||
description: "Reset Theme Color",
|
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
default: "313338",
|
|
||||||
component: () => (
|
component: () => (
|
||||||
<Button onClick={() => onPickColor(0x313338)}>
|
<Button onClick={() => onPickColor(0x313338)}>
|
||||||
Reset Theme Color
|
Reset Theme Color
|
||||||
|
|
|
@ -44,6 +44,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: ".selectPreviousCommandOption(",
|
find: ".selectPreviousCommandOption(",
|
||||||
replacement: {
|
replacement: {
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(?<=(\i)\.which(?:!==|===)\i\.\i.ENTER(\|\||&&)).{0,100}(\(0,\i\.\i\)\(\i\)).{0,100}(?=(?:\|\||&&)\(\i\.preventDefault)/,
|
match: /(?<=(\i)\.which(?:!==|===)\i\.\i.ENTER(\|\||&&)).{0,100}(\(0,\i\.\i\)\(\i\)).{0,100}(?=(?:\|\||&&)\(\i\.preventDefault)/,
|
||||||
replace: (_, event, condition, codeblock) => `${condition === "||" ? "!" : ""}$self.shouldSubmit(${event},${codeblock})`
|
replace: (_, event, condition, codeblock) => `${condition === "||" ? "!" : ""}$self.shouldSubmit(${event},${codeblock})`
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import DecorSection from "./ui/components/DecorSection";
|
||||||
export const settings = definePluginSettings({
|
export const settings = definePluginSettings({
|
||||||
changeDecoration: {
|
changeDecoration: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "Change your avatar decoration",
|
|
||||||
component() {
|
component() {
|
||||||
if (!Vencord.Plugins.plugins.Decor.started) return <Forms.FormText>
|
if (!Vencord.Plugins.plugins.Decor.started) return <Forms.FormText>
|
||||||
Enable Decor and restart your client to change your avatar decoration.
|
Enable Decor and restart your client to change your avatar decoration.
|
||||||
|
|
|
@ -256,6 +256,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Disallow the emoji for premium locked if the intention doesn't allow it
|
// Disallow the emoji for premium locked if the intention doesn't allow it
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(!)?(\i\.\i\.canUseEmojisEverywhere\(\i\))/,
|
match: /(!)?(\i\.\i\.canUseEmojisEverywhere\(\i\))/,
|
||||||
replace: (m, not) => not
|
replace: (m, not) => not
|
||||||
? `(${m}&&!${IS_BYPASSEABLE_INTENTION})`
|
? `(${m}&&!${IS_BYPASSEABLE_INTENTION})`
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin from "@utils/types";
|
import definePlugin from "@utils/types";
|
||||||
import { findComponentByCodeLazy } from "@webpack";
|
import { findComponentByCodeLazy } from "@webpack";
|
||||||
|
import { UserStore, useStateFromStores } from "@webpack/common";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
const UserMentionComponent = findComponentByCodeLazy(".USER_MENTION)");
|
const UserMentionComponent = findComponentByCodeLazy(".USER_MENTION)");
|
||||||
|
@ -34,14 +35,19 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
UserMentionComponent: ErrorBoundary.wrap((props: UserMentionComponentProps) => (
|
UserMentionComponent: ErrorBoundary.wrap((props: UserMentionComponentProps) => {
|
||||||
<UserMentionComponent
|
const user = useStateFromStores([UserStore], () => UserStore.getUser(props.id));
|
||||||
|
if (user == null) {
|
||||||
|
return props.originalComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return <UserMentionComponent
|
||||||
// This seems to be constant
|
// This seems to be constant
|
||||||
className="mention"
|
className="mention"
|
||||||
userId={props.id}
|
userId={props.id}
|
||||||
channelId={props.channelId}
|
channelId={props.channelId}
|
||||||
/>
|
/>;
|
||||||
), {
|
}, {
|
||||||
fallback: ({ wrappedProps: { originalComponent } }) => originalComponent()
|
fallback: ({ wrappedProps: { originalComponent } }) => originalComponent()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -147,8 +147,7 @@ function IdsListComponent(props: { setValue: (value: string) => void; }) {
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
importCustomRPC: {
|
importCustomRPC: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "",
|
component: ImportCustomRPCComponent
|
||||||
component: () => <ImportCustomRPCComponent />
|
|
||||||
},
|
},
|
||||||
listMode: {
|
listMode: {
|
||||||
type: OptionType.SELECT,
|
type: OptionType.SELECT,
|
||||||
|
@ -168,7 +167,6 @@ const settings = definePluginSettings({
|
||||||
},
|
},
|
||||||
idsList: {
|
idsList: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "",
|
|
||||||
default: "",
|
default: "",
|
||||||
onChange(newValue: string) {
|
onChange(newValue: string) {
|
||||||
const ids = new Set(newValue.split(",").map(id => id.trim()).filter(Boolean));
|
const ids = new Set(newValue.split(",").map(id => id.trim()).filter(Boolean));
|
||||||
|
@ -243,7 +241,7 @@ export default definePlugin({
|
||||||
find: '"LocalActivityStore"',
|
find: '"LocalActivityStore"',
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /HANG_STATUS.+?(?=!?\i\(\)\(\i,\i\))(?<=(\i)\.push.+?)/,
|
match: /\.LISTENING.+?(?=!?\i\(\)\(\i,\i\))(?<=(\i)\.push.+?)/,
|
||||||
replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);`
|
replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -50,9 +50,9 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: "#{intl::FRIENDS_SECTION_ONLINE}",
|
find: "#{intl::FRIENDS_SECTION_ONLINE}",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(\(0,\i\.jsx\)\(\i\.\i\.Item,\{id:\i\.\i)\.BLOCKED,className:([^\s]+?)\.item,children:\i\.\i\.string\(\i\.\i#{intl::BLOCKED}\)\}\)/,
|
match: /,{id:(\i\.\i)\.BLOCKED,show:.+?className:(\i\.item)/,
|
||||||
replace: "$1.IMPLICIT,className:$2.item,children:\"Implicit\"}),$&"
|
replace: (rest, relationShipTypes, className) => `,{id:${relationShipTypes}.IMPLICIT,show:true,className:${className},content:"Implicit"}${rest}`
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
// Sections content
|
// Sections content
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,11 +23,11 @@ import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { useMemo } from "@webpack/common";
|
import { useMemo } from "@webpack/common";
|
||||||
|
|
||||||
// Calculate a CSS color string based on the user ID
|
// Calculate a CSS color string based on the user ID
|
||||||
function calculateNameColorForUser(id: string) {
|
function calculateNameColorForUser(id?: string) {
|
||||||
const { lightness } = settings.use(["lightness"]);
|
const { lightness } = settings.use(["lightness"]);
|
||||||
const idHash = useMemo(() => h64(id), [id]);
|
const idHash = useMemo(() => id ? h64(id) : null, [id]);
|
||||||
|
|
||||||
return `hsl(${idHash % 360n}, 100%, ${lightness}%)`;
|
return idHash && `hsl(${idHash % 360n}, 100%, ${lightness}%)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
|
@ -41,13 +41,25 @@ const settings = definePluginSettings({
|
||||||
restartNeeded: true,
|
restartNeeded: true,
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
applyColorOnlyToUsersWithoutColor: {
|
||||||
|
description: "Apply colors only to users who don't have a predefined color",
|
||||||
|
restartNeeded: false,
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
applyColorOnlyInDms: {
|
||||||
|
description: "Apply colors only in direct messages; do not apply colors in servers.",
|
||||||
|
restartNeeded: false,
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "IrcColors",
|
name: "IrcColors",
|
||||||
description: "Makes username colors in chat unique, like in IRC clients",
|
description: "Makes username colors in chat unique, like in IRC clients",
|
||||||
authors: [Devs.Grzesiek11],
|
authors: [Devs.Grzesiek11, Devs.jamesbt365],
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
|
@ -70,16 +82,28 @@ export default definePlugin({
|
||||||
|
|
||||||
calculateNameColorForMessageContext(context: any) {
|
calculateNameColorForMessageContext(context: any) {
|
||||||
const id = context?.message?.author?.id;
|
const id = context?.message?.author?.id;
|
||||||
if (id == null) {
|
const colorString = context?.author?.colorString;
|
||||||
return null;
|
const color = calculateNameColorForUser(id);
|
||||||
|
|
||||||
|
if (settings.store.applyColorOnlyInDms && !context?.channel?.isPrivate()) {
|
||||||
|
return colorString;
|
||||||
}
|
}
|
||||||
return calculateNameColorForUser(id);
|
|
||||||
|
return (!settings.store.applyColorOnlyToUsersWithoutColor || !colorString)
|
||||||
|
? color
|
||||||
|
: colorString;
|
||||||
},
|
},
|
||||||
calculateNameColorForListContext(context: any) {
|
calculateNameColorForListContext(context: any) {
|
||||||
const id = context?.user?.id;
|
const id = context?.user?.id;
|
||||||
if (id == null) {
|
const colorString = context?.colorString;
|
||||||
return null;
|
const color = calculateNameColorForUser(id);
|
||||||
|
|
||||||
|
if (settings.store.applyColorOnlyInDms && !context?.channel?.isPrivate()) {
|
||||||
|
return colorString;
|
||||||
}
|
}
|
||||||
return calculateNameColorForUser(id);
|
|
||||||
|
return (!settings.store.applyColorOnlyToUsersWithoutColor || !colorString)
|
||||||
|
? color
|
||||||
|
: colorString;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -120,11 +120,11 @@ const settings = definePluginSettings({
|
||||||
},
|
},
|
||||||
clearMessageCache: {
|
clearMessageCache: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "Clear the linked message cache",
|
component: () => (
|
||||||
component: () =>
|
|
||||||
<Button onClick={() => messageCache.clear()}>
|
<Button onClick={() => messageCache.clear()}>
|
||||||
Clear the linked message cache
|
Clear the linked message cache
|
||||||
</Button>
|
</Button>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ export default definePlugin({
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
// TODO: Remove DataStore tags migration once enough time has passed
|
// TODO(OptionType.CUSTOM Related): Remove DataStore tags migration once enough time has passed
|
||||||
const oldTags = await DataStore.get<Tag[]>(DATA_KEY);
|
const oldTags = await DataStore.get<Tag[]>(DATA_KEY);
|
||||||
if (oldTags != null) {
|
if (oldTags != null) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -1,42 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { getUserSettingLazy } from "@api/UserSettings";
|
|
||||||
import { Devs } from "@utils/constants";
|
|
||||||
import definePlugin from "@utils/types";
|
|
||||||
|
|
||||||
const DisableStreamPreviews = getUserSettingLazy<boolean>("voiceAndVideo", "disableStreamPreviews")!;
|
|
||||||
|
|
||||||
// @TODO: Delete this plugin in the future
|
|
||||||
export default definePlugin({
|
|
||||||
name: "NoScreensharePreview",
|
|
||||||
description: "Disables screenshare previews from being sent.",
|
|
||||||
authors: [Devs.Nuckyz],
|
|
||||||
|
|
||||||
start() {
|
|
||||||
if (!DisableStreamPreviews.getSetting()) {
|
|
||||||
DisableStreamPreviews.updateSetting(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
if (DisableStreamPreviews.getSetting()) {
|
|
||||||
DisableStreamPreviews.updateSetting(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -25,9 +25,9 @@ export default definePlugin({
|
||||||
settings,
|
settings,
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "_ensureAudio(){",
|
find: "ensureAudio(){",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?=Math\.min\(\i\.\i\.getOutputVolume\(\)\/100)/,
|
match: /(?=Math\.min\(\i\.\i\.getOutputVolume\(\)\/100)/g,
|
||||||
replace: "$self.settings.store.notificationVolume/100*"
|
replace: "$self.settings.store.notificationVolume/100*"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -100,6 +100,7 @@ export default definePlugin({
|
||||||
replace: "true"
|
replace: "true"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(!)?\(0,\i\.isDesktop\)\(\)/,
|
match: /(!)?\(0,\i\.isDesktop\)\(\)/,
|
||||||
replace: (_, not) => not ? "false" : "true"
|
replace: (_, not) => not ? "false" : "true"
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ export default definePlugin({
|
||||||
find: "#{intl::ONBOARDING_CHANNEL_THRESHOLD_WARNING}",
|
find: "#{intl::ONBOARDING_CHANNEL_THRESHOLD_WARNING}",
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /{(?:\i:(?:function\(\){return |\(\)=>)\i}?,?){2}}/,
|
match: /{(?:\i:(?:function\(\){return |\(\)=>)\i}?,?){2}}/,
|
||||||
replace: m => m.replaceAll(canonicalizeMatch(/(function\(\){return |\(\)=>)\i/g), "$1()=>Promise.resolve(true)")
|
replace: m => m.replaceAll(canonicalizeMatch(/(function\(\){return |\(\)=>)\i/g), "$1()=>Promise.resolve(true)")
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ export function moveChannel(channelId: string, direction: -1 | 1) {
|
||||||
swapElementsInArray(category.channels, a, b);
|
swapElementsInArray(category.channels, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove DataStore PinnedDms migration once enough time has passed
|
// TODO(OptionType.CUSTOM Related): Remove DataStore PinnedDms migration once enough time has passed
|
||||||
async function migrateData() {
|
async function migrateData() {
|
||||||
if (Settings.plugins.PinDMs.dmSectioncollapsed != null) {
|
if (Settings.plugins.PinDMs.dmSectioncollapsed != null) {
|
||||||
settings.store.dmSectionCollapsed = Settings.plugins.PinDMs.dmSectioncollapsed;
|
settings.store.dmSectionCollapsed = Settings.plugins.PinDMs.dmSectioncollapsed;
|
||||||
|
|
|
@ -196,7 +196,7 @@ function nextReply(isUp: boolean) {
|
||||||
channel,
|
channel,
|
||||||
message,
|
message,
|
||||||
shouldMention: shouldMention(message),
|
shouldMention: shouldMention(message),
|
||||||
showMentionToggle: channel.isPrivate() && message.author.id !== meId,
|
showMentionToggle: !channel.isPrivate() && message.author.id !== meId,
|
||||||
_isQuickReply: true
|
_isQuickReply: true
|
||||||
});
|
});
|
||||||
ComponentDispatch.dispatchToLastSubscribed("TEXTAREA_FOCUS");
|
ComponentDispatch.dispatchToLastSubscribed("TEXTAREA_FOCUS");
|
||||||
|
|
|
@ -7,15 +7,12 @@
|
||||||
import { DataStore } from "@api/index";
|
import { DataStore } from "@api/index";
|
||||||
import { Logger } from "@utils/Logger";
|
import { Logger } from "@utils/Logger";
|
||||||
import { openModal } from "@utils/modal";
|
import { openModal } from "@utils/modal";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { OAuth2AuthorizeModal, showToast, Toasts, UserStore } from "@webpack/common";
|
||||||
import { showToast, Toasts, UserStore } from "@webpack/common";
|
|
||||||
|
|
||||||
import { ReviewDBAuth } from "./entities";
|
import { ReviewDBAuth } from "./entities";
|
||||||
|
|
||||||
const DATA_STORE_KEY = "rdb-auth";
|
const DATA_STORE_KEY = "rdb-auth";
|
||||||
|
|
||||||
const { OAuth2AuthorizeModal } = findByPropsLazy("OAuth2AuthorizeModal");
|
|
||||||
|
|
||||||
export let Auth: ReviewDBAuth = {};
|
export let Auth: ReviewDBAuth = {};
|
||||||
|
|
||||||
export async function initAuth() {
|
export async function initAuth() {
|
||||||
|
|
|
@ -27,7 +27,6 @@ import { cl } from "./utils";
|
||||||
export const settings = definePluginSettings({
|
export const settings = definePluginSettings({
|
||||||
authorize: {
|
authorize: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "Authorize with ReviewDB",
|
|
||||||
component: () => (
|
component: () => (
|
||||||
<Button onClick={() => authorize()}>
|
<Button onClick={() => authorize()}>
|
||||||
Authorize with ReviewDB
|
Authorize with ReviewDB
|
||||||
|
@ -56,7 +55,6 @@ export const settings = definePluginSettings({
|
||||||
},
|
},
|
||||||
buttons: {
|
buttons: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "ReviewDB buttons",
|
|
||||||
component: () => (
|
component: () => (
|
||||||
<div className={cl("button-grid")} >
|
<div className={cl("button-grid")} >
|
||||||
<Button onClick={openBlockModal}>Manage Blocked Users</Button>
|
<Button onClick={openBlockModal}>Manage Blocked Users</Button>
|
||||||
|
|
|
@ -108,6 +108,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Prevent Discord from trying to connect to hidden voice channels
|
// Prevent Discord from trying to connect to hidden voice channels
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(?=(\|\||&&)\i\.\i\.selectVoiceChannel\((\i)\.id\))/,
|
match: /(?=(\|\||&&)\i\.\i\.selectVoiceChannel\((\i)\.id\))/,
|
||||||
replace: (_, condition, channel) => condition === "||"
|
replace: (_, condition, channel) => condition === "||"
|
||||||
? `||$self.isHiddenChannel(${channel})`
|
? `||$self.isHiddenChannel(${channel})`
|
||||||
|
@ -124,6 +125,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: ".AUDIENCE),{isSubscriptionGated",
|
find: ".AUDIENCE),{isSubscriptionGated",
|
||||||
replacement: {
|
replacement: {
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(!)?(\i)\.isRoleSubscriptionTemplatePreviewChannel\(\)/,
|
match: /(!)?(\i)\.isRoleSubscriptionTemplatePreviewChannel\(\)/,
|
||||||
replace: (m, not, channel) => not
|
replace: (m, not, channel) => not
|
||||||
? `${m}&&!$self.isHiddenChannel(${channel})`
|
? `${m}&&!$self.isHiddenChannel(${channel})`
|
||||||
|
@ -177,6 +179,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// Make voice channels also appear as muted if they are muted
|
// Make voice channels also appear as muted if they are muted
|
||||||
{
|
{
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(?<=\.wrapper:\i\.notInteractive,)(.+?)(if\()?(\i)(?:\)return |\?)(\i\.MUTED)/,
|
match: /(?<=\.wrapper:\i\.notInteractive,)(.+?)(if\()?(\i)(?:\)return |\?)(\i\.MUTED)/,
|
||||||
replace: (_, otherClasses, isIf, isMuted, mutedClassExpression) => isIf
|
replace: (_, otherClasses, isIf, isMuted, mutedClassExpression) => isIf
|
||||||
? `${isMuted}?${mutedClassExpression}:"",${otherClasses}if(${isMuted})return ""`
|
? `${isMuted}?${mutedClassExpression}:"",${otherClasses}if(${isMuted})return ""`
|
||||||
|
@ -190,6 +193,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
// Make muted channels also appear as unread if hide unreads is false, using the HiddenIconWithMutedStyle and the channel is hidden
|
// Make muted channels also appear as unread if hide unreads is false, using the HiddenIconWithMutedStyle and the channel is hidden
|
||||||
predicate: () => settings.store.hideUnreads === false && settings.store.showMode === ShowMode.HiddenIconWithMutedStyle,
|
predicate: () => settings.store.hideUnreads === false && settings.store.showMode === ShowMode.HiddenIconWithMutedStyle,
|
||||||
|
// FIXME(Bundler change related): Remove old compatiblity once enough time has passed
|
||||||
match: /(?<=\.LOCKED(?:;if\(|:))(?<={channel:(\i).+?)/,
|
match: /(?<=\.LOCKED(?:;if\(|:))(?<={channel:(\i).+?)/,
|
||||||
replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&`
|
replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&`
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,7 +45,6 @@ const makeEmptyRuleArray = () => [makeEmptyRule()];
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
replace: {
|
replace: {
|
||||||
type: OptionType.COMPONENT,
|
type: OptionType.COMPONENT,
|
||||||
description: "",
|
|
||||||
component: () => {
|
component: () => {
|
||||||
const { stringRules, regexRules } = settings.use(["stringRules", "regexRules"]);
|
const { stringRules, regexRules } = settings.use(["stringRules", "regexRules"]);
|
||||||
|
|
||||||
|
@ -245,7 +244,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
// TODO: Remove DataStore rules migrations once enough time has passed
|
// TODO(OptionType.CUSTOM Related): Remove DataStore rules migrations once enough time has passed
|
||||||
const oldStringRules = await DataStore.get<Rule[]>(STRING_RULES_KEY);
|
const oldStringRules = await DataStore.get<Rule[]>(STRING_RULES_KEY);
|
||||||
if (oldStringRules != null) {
|
if (oldStringRules != null) {
|
||||||
settings.store.stringRules = oldStringRules;
|
settings.store.stringRules = oldStringRules;
|
||||||
|
|
|
@ -100,16 +100,24 @@ function TypingIndicator({ channelId, guildId }: { channelId: string; guildId: s
|
||||||
{props => (
|
{props => (
|
||||||
<div className="vc-typing-indicator" {...props}>
|
<div className="vc-typing-indicator" {...props}>
|
||||||
{((settings.store.indicatorMode & IndicatorMode.Avatars) === IndicatorMode.Avatars) && (
|
{((settings.store.indicatorMode & IndicatorMode.Avatars) === IndicatorMode.Avatars) && (
|
||||||
<UserSummaryItem
|
<div
|
||||||
users={typingUsersArray.map(id => UserStore.getUser(id))}
|
onClick={e => {
|
||||||
guildId={guildId}
|
e.stopPropagation();
|
||||||
renderIcon={false}
|
e.preventDefault();
|
||||||
max={3}
|
}}
|
||||||
showDefaultAvatarsForNullUsers
|
onKeyPress={e => e.stopPropagation()}
|
||||||
showUserPopout
|
>
|
||||||
size={16}
|
<UserSummaryItem
|
||||||
className="vc-typing-indicator-avatars"
|
users={typingUsersArray.map(id => UserStore.getUser(id))}
|
||||||
/>
|
guildId={guildId}
|
||||||
|
renderIcon={false}
|
||||||
|
max={3}
|
||||||
|
showDefaultAvatarsForNullUsers
|
||||||
|
showUserPopout
|
||||||
|
size={16}
|
||||||
|
className="vc-typing-indicator-avatars"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{((settings.store.indicatorMode & IndicatorMode.Dots) === IndicatorMode.Dots) && (
|
{((settings.store.indicatorMode & IndicatorMode.Dots) === IndicatorMode.Dots) && (
|
||||||
<div className="vc-typing-indicator-dots">
|
<div className="vc-typing-indicator-dots">
|
||||||
|
|
|
@ -20,10 +20,13 @@ import { definePluginSettings } from "@api/Settings";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { saveFile } from "@utils/web";
|
import { saveFile } from "@utils/web";
|
||||||
import { findByPropsLazy } from "@webpack";
|
import { filters, mapMangledModuleLazy } from "@webpack";
|
||||||
import { Clipboard, ComponentDispatch } from "@webpack/common";
|
import { Clipboard, ComponentDispatch } from "@webpack/common";
|
||||||
|
|
||||||
const ctxMenuCallbacks = findByPropsLazy("contextMenuCallbackNative");
|
const ctxMenuCallbacks = mapMangledModuleLazy('.tagName)==="TEXTAREA"||', {
|
||||||
|
contextMenuCallbackWeb: filters.byCode('.tagName)==="INPUT"||'),
|
||||||
|
contextMenuCallbackNative: filters.byCode('.tagName)==="TEXTAREA"||')
|
||||||
|
});
|
||||||
|
|
||||||
async function fetchImage(url: string) {
|
async function fetchImage(url: string) {
|
||||||
const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
|
|
|
@ -93,7 +93,7 @@ function makeRenderMoreUsers(users: User[]) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClickAvatar(event: React.MouseEvent<HTMLElement, MouseEvent>) {
|
function handleClickAvatar(event: React.UIEvent<HTMLElement, Event>) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ export default definePlugin({
|
||||||
<div
|
<div
|
||||||
style={{ marginLeft: "0.5em", transform: "scale(0.9)" }}
|
style={{ marginLeft: "0.5em", transform: "scale(0.9)" }}
|
||||||
>
|
>
|
||||||
<div onClick={handleClickAvatar}>
|
<div onClick={handleClickAvatar} onKeyPress={handleClickAvatar}>
|
||||||
<UserSummaryItem
|
<UserSummaryItem
|
||||||
users={users}
|
users={users}
|
||||||
guildId={ChannelStore.getChannel(message.channel_id)?.guild_id}
|
guildId={ChannelStore.getChannel(message.channel_id)?.guild_id}
|
||||||
|
|
|
@ -101,7 +101,7 @@ interface Modals {
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Modals: Modals = mapMangledModuleLazy(':"thin")', {
|
export const Modals: Modals = mapMangledModuleLazy(':"thin")', {
|
||||||
ModalRoot: filters.componentByCode('.MODAL,"aria-labelledby":'),
|
ModalRoot: filters.componentByCode('.MODAL,"aria-labelledby":'),
|
||||||
ModalHeader: filters.componentByCode(",id:"),
|
ModalHeader: filters.componentByCode(",id:"),
|
||||||
ModalContent: filters.componentByCode(".content,"),
|
ModalContent: filters.componentByCode(".content,"),
|
||||||
|
|
|
@ -198,15 +198,16 @@ export type SettingsChecks<D extends SettingsDefinition> = {
|
||||||
(IsDisabled<DefinedSettings<D>> & IsValid<PluginSettingType<D[K]>, DefinedSettings<D>>);
|
(IsDisabled<DefinedSettings<D>> & IsValid<PluginSettingType<D[K]>, DefinedSettings<D>>);
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PluginSettingDef = (PluginSettingCustomDef & Pick<PluginSettingCommon, "onChange">) | ((
|
export type PluginSettingDef =
|
||||||
| PluginSettingStringDef
|
(PluginSettingCustomDef & Pick<PluginSettingCommon, "onChange">) |
|
||||||
| PluginSettingNumberDef
|
(PluginSettingComponentDef & Omit<PluginSettingCommon, "description" | "placeholder">) | ((
|
||||||
| PluginSettingBooleanDef
|
| PluginSettingStringDef
|
||||||
| PluginSettingSelectDef
|
| PluginSettingNumberDef
|
||||||
| PluginSettingSliderDef
|
| PluginSettingBooleanDef
|
||||||
| PluginSettingComponentDef
|
| PluginSettingSelectDef
|
||||||
| PluginSettingBigIntDef
|
| PluginSettingSliderDef
|
||||||
) & PluginSettingCommon);
|
| PluginSettingBigIntDef
|
||||||
|
) & PluginSettingCommon);
|
||||||
|
|
||||||
export interface PluginSettingCommon {
|
export interface PluginSettingCommon {
|
||||||
description: string;
|
description: string;
|
||||||
|
@ -226,12 +227,14 @@ export interface PluginSettingCommon {
|
||||||
*/
|
*/
|
||||||
target?: "WEB" | "DESKTOP" | "BOTH";
|
target?: "WEB" | "DESKTOP" | "BOTH";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IsDisabled<D = unknown> {
|
interface IsDisabled<D = unknown> {
|
||||||
/**
|
/**
|
||||||
* Checks if this setting should be disabled
|
* Checks if this setting should be disabled
|
||||||
*/
|
*/
|
||||||
disabled?(this: D): boolean;
|
disabled?(this: D): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IsValid<T, D = unknown> {
|
interface IsValid<T, D = unknown> {
|
||||||
/**
|
/**
|
||||||
* Prevents the user from saving settings if this is false or a string
|
* Prevents the user from saving settings if this is false or a string
|
||||||
|
@ -320,7 +323,7 @@ type PluginSettingType<O extends PluginSettingDef> = O extends PluginSettingStri
|
||||||
O extends PluginSettingBooleanDef ? boolean :
|
O extends PluginSettingBooleanDef ? boolean :
|
||||||
O extends PluginSettingSelectDef ? O["options"][number]["value"] :
|
O extends PluginSettingSelectDef ? O["options"][number]["value"] :
|
||||||
O extends PluginSettingSliderDef ? number :
|
O extends PluginSettingSliderDef ? number :
|
||||||
O extends PluginSettingComponentDef ? any :
|
O extends PluginSettingComponentDef ? O extends { default: infer Default; } ? Default : any :
|
||||||
O extends PluginSettingCustomDef ? O extends { default: infer Default; } ? Default : any :
|
O extends PluginSettingCustomDef ? O extends { default: infer Default; } ? Default : any :
|
||||||
never;
|
never;
|
||||||
|
|
||||||
|
@ -382,7 +385,7 @@ export type PluginOptionNumber = (PluginSettingNumberDef | PluginSettingBigIntDe
|
||||||
export type PluginOptionBoolean = PluginSettingBooleanDef & PluginSettingCommon & IsDisabled & IsValid<boolean>;
|
export type PluginOptionBoolean = PluginSettingBooleanDef & PluginSettingCommon & IsDisabled & IsValid<boolean>;
|
||||||
export type PluginOptionSelect = PluginSettingSelectDef & PluginSettingCommon & IsDisabled & IsValid<PluginSettingSelectOption>;
|
export type PluginOptionSelect = PluginSettingSelectDef & PluginSettingCommon & IsDisabled & IsValid<PluginSettingSelectOption>;
|
||||||
export type PluginOptionSlider = PluginSettingSliderDef & PluginSettingCommon & IsDisabled & IsValid<number>;
|
export type PluginOptionSlider = PluginSettingSliderDef & PluginSettingCommon & IsDisabled & IsValid<number>;
|
||||||
export type PluginOptionComponent = PluginSettingComponentDef & PluginSettingCommon;
|
export type PluginOptionComponent = PluginSettingComponentDef & Omit<PluginSettingCommon, "description" | "placeholder">;
|
||||||
export type PluginOptionCustom = PluginSettingCustomDef & Pick<PluginSettingCommon, "onChange">;
|
export type PluginOptionCustom = PluginSettingCustomDef & Pick<PluginSettingCommon, "onChange">;
|
||||||
|
|
||||||
export type PluginNative<PluginExports extends Record<string, (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any>> = {
|
export type PluginNative<PluginExports extends Record<string, (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any>> = {
|
||||||
|
|
|
@ -95,3 +95,8 @@ export const MaskedLink = waitForComponent<t.MaskedLink>("MaskedLink", filters.c
|
||||||
export const Timestamp = waitForComponent<t.Timestamp>("Timestamp", filters.componentByCode("#{intl::MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL}"));
|
export const Timestamp = waitForComponent<t.Timestamp>("Timestamp", filters.componentByCode("#{intl::MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL}"));
|
||||||
export const Flex = waitForComponent<t.Flex>("Flex", ["Justify", "Align", "Wrap"]);
|
export const Flex = waitForComponent<t.Flex>("Flex", ["Justify", "Align", "Wrap"]);
|
||||||
export const OAuth2AuthorizeModal = waitForComponent("OAuth2AuthorizeModal", filters.componentByCode(".authorize),children:", ".contentBackground"));
|
export const OAuth2AuthorizeModal = waitForComponent("OAuth2AuthorizeModal", filters.componentByCode(".authorize),children:", ".contentBackground"));
|
||||||
|
|
||||||
|
export const Animations = mapMangledModuleLazy(".assign({colorNames:", {
|
||||||
|
Transition: filters.componentByCode('["items","children"]', ",null,"),
|
||||||
|
animated: filters.byProps("div", "text")
|
||||||
|
});
|
||||||
|
|
|
@ -36,6 +36,7 @@ waitFor(m => m.name === "MenuCheckboxItem", (_, id) => {
|
||||||
|
|
||||||
waitFor(filters.componentByCode('path:["empty"]'), m => Menu.Menu = m);
|
waitFor(filters.componentByCode('path:["empty"]'), m => Menu.Menu = m);
|
||||||
waitFor(filters.componentByCode("sliderContainer", "slider", "handleSize:16", "=100"), m => Menu.MenuSliderControl = m);
|
waitFor(filters.componentByCode("sliderContainer", "slider", "handleSize:16", "=100"), m => Menu.MenuSliderControl = m);
|
||||||
|
waitFor(filters.componentByCode('role:"searchbox', "top:2", "query:"), m => Menu.MenuSearchControl = m);
|
||||||
|
|
||||||
export const ContextMenuApi: t.ContextMenuApi = mapMangledModuleLazy('type:"CONTEXT_MENU_OPEN', {
|
export const ContextMenuApi: t.ContextMenuApi = mapMangledModuleLazy('type:"CONTEXT_MENU_OPEN', {
|
||||||
closeContextMenu: filters.byCode("CONTEXT_MENU_CLOSE"),
|
closeContextMenu: filters.byCode("CONTEXT_MENU_CLOSE"),
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { WebpackInstance } from "discord-types/other";
|
||||||
|
|
||||||
import { traceFunction } from "../debug/Tracer";
|
import { traceFunction } from "../debug/Tracer";
|
||||||
import { patches } from "../plugins";
|
import { patches } from "../plugins";
|
||||||
import { _initWebpack, beforeInitListeners, factoryListeners, moduleListeners, subscriptions, wreq } from ".";
|
import { _initWebpack, _shouldIgnoreModule, beforeInitListeners, factoryListeners, moduleListeners, subscriptions, wreq } from ".";
|
||||||
|
|
||||||
const logger = new Logger("WebpackInterceptor", "#8caaee");
|
const logger = new Logger("WebpackInterceptor", "#8caaee");
|
||||||
|
|
||||||
|
@ -173,35 +173,9 @@ function patchFactories(factories: Record<string, (module: any, exports: any, re
|
||||||
if (!exports) return;
|
if (!exports) return;
|
||||||
|
|
||||||
if (require.c) {
|
if (require.c) {
|
||||||
let shouldMakeNonEnumerable = false;
|
const shouldIgnoreModule = _shouldIgnoreModule(exports);
|
||||||
|
|
||||||
nonEnumerableChecking: {
|
if (shouldIgnoreModule) {
|
||||||
// There are (at the time of writing) 11 modules exporting the window,
|
|
||||||
// and also modules exporting DOMTokenList, which breaks webpack finding
|
|
||||||
// Make these non enumerable to improve search performance and avoid erros
|
|
||||||
if (exports === window || exports[Symbol.toStringTag] === "DOMTokenList") {
|
|
||||||
shouldMakeNonEnumerable = true;
|
|
||||||
break nonEnumerableChecking;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof exports !== "object") {
|
|
||||||
break nonEnumerableChecking;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exports.default === window || exports.default?.[Symbol.toStringTag] === "DOMTokenList") {
|
|
||||||
shouldMakeNonEnumerable = true;
|
|
||||||
break nonEnumerableChecking;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const nested in exports) {
|
|
||||||
if (exports[nested] === window || exports[nested]?.[Symbol.toStringTag] === "DOMTokenList") {
|
|
||||||
shouldMakeNonEnumerable = true;
|
|
||||||
break nonEnumerableChecking;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldMakeNonEnumerable) {
|
|
||||||
Object.defineProperty(require.c, id, {
|
Object.defineProperty(require.c, id, {
|
||||||
value: require.c[id],
|
value: require.c[id],
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
|
@ -226,17 +200,16 @@ function patchFactories(factories: Record<string, (module: any, exports: any, re
|
||||||
if (exports && filter(exports)) {
|
if (exports && filter(exports)) {
|
||||||
subscriptions.delete(filter);
|
subscriptions.delete(filter);
|
||||||
callback(exports, id);
|
callback(exports, id);
|
||||||
} else if (typeof exports === "object") {
|
}
|
||||||
if (exports.default && filter(exports.default)) {
|
|
||||||
|
if (typeof exports !== "object") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const exportKey in exports) {
|
||||||
|
if (exports[exportKey] && filter(exports[exportKey])) {
|
||||||
subscriptions.delete(filter);
|
subscriptions.delete(filter);
|
||||||
callback(exports.default, id);
|
callback(exports[exportKey], id);
|
||||||
} else {
|
|
||||||
for (const nested in exports) {
|
|
||||||
if (exports[nested] && filter(exports[nested])) {
|
|
||||||
subscriptions.delete(filter);
|
|
||||||
callback(exports[nested], id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -71,13 +71,16 @@ export const filters = {
|
||||||
componentByCode: (...code: CodeFilter): FilterFn => {
|
componentByCode: (...code: CodeFilter): FilterFn => {
|
||||||
const filter = filters.byCode(...code);
|
const filter = filters.byCode(...code);
|
||||||
return m => {
|
return m => {
|
||||||
if (filter(m)) return true;
|
let inner = m;
|
||||||
if (!m.$$typeof) return false;
|
|
||||||
if (m.type)
|
while (inner != null) {
|
||||||
return m.type.render
|
if (filter(inner)) return true;
|
||||||
? filter(m.type.render) // memo + forwardRef
|
else if (!inner.$$typeof) return false;
|
||||||
: filter(m.type); // memo
|
else if (inner.type) inner = inner.type; // memos
|
||||||
if (m.render) return filter(m.render); // forwardRef
|
else if (inner.render) inner = inner.render; // forwardRefs
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -95,6 +98,38 @@ export function _initWebpack(webpackRequire: WebpackInstance) {
|
||||||
cache = webpackRequire.c;
|
cache = webpackRequire.c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Credits to Zerebos for implementing this in BD, thus giving the idea for us to implement it too
|
||||||
|
const TypedArray = Object.getPrototypeOf(Int8Array);
|
||||||
|
|
||||||
|
function _shouldIgnoreValue(value: any) {
|
||||||
|
if (value == null) return true;
|
||||||
|
if (value === window) return true;
|
||||||
|
if (value === document || value === document.documentElement) return true;
|
||||||
|
if (value[Symbol.toStringTag] === "DOMTokenList") return true;
|
||||||
|
if (value instanceof TypedArray) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function _shouldIgnoreModule(exports: any) {
|
||||||
|
if (_shouldIgnoreValue(exports)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof exports !== "object") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let allNonEnumerable = true;
|
||||||
|
for (const exportKey in exports) {
|
||||||
|
if (!_shouldIgnoreValue(exports[exportKey])) {
|
||||||
|
allNonEnumerable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allNonEnumerable;
|
||||||
|
}
|
||||||
|
|
||||||
let devToolsOpen = false;
|
let devToolsOpen = false;
|
||||||
if (IS_DEV && IS_DISCORD_DESKTOP) {
|
if (IS_DEV && IS_DISCORD_DESKTOP) {
|
||||||
// At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed
|
// At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed
|
||||||
|
@ -121,7 +156,7 @@ export const find = traceFunction("find", function find(filter: FilterFn, { isIn
|
||||||
|
|
||||||
for (const key in cache) {
|
for (const key in cache) {
|
||||||
const mod = cache[key];
|
const mod = cache[key];
|
||||||
if (!mod.loaded || !mod?.exports) continue;
|
if (!mod?.loaded || mod.exports == null) continue;
|
||||||
|
|
||||||
if (filter(mod.exports)) {
|
if (filter(mod.exports)) {
|
||||||
return isWaitFor ? [mod.exports, key] : mod.exports;
|
return isWaitFor ? [mod.exports, key] : mod.exports;
|
||||||
|
@ -129,11 +164,6 @@ export const find = traceFunction("find", function find(filter: FilterFn, { isIn
|
||||||
|
|
||||||
if (typeof mod.exports !== "object") continue;
|
if (typeof mod.exports !== "object") continue;
|
||||||
|
|
||||||
if (mod.exports.default && filter(mod.exports.default)) {
|
|
||||||
const found = mod.exports.default;
|
|
||||||
return isWaitFor ? [found, key] : found;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const nestedMod in mod.exports) {
|
for (const nestedMod in mod.exports) {
|
||||||
const nested = mod.exports[nestedMod];
|
const nested = mod.exports[nestedMod];
|
||||||
if (nested && filter(nested)) {
|
if (nested && filter(nested)) {
|
||||||
|
@ -156,16 +186,15 @@ export function findAll(filter: FilterFn) {
|
||||||
const ret = [] as any[];
|
const ret = [] as any[];
|
||||||
for (const key in cache) {
|
for (const key in cache) {
|
||||||
const mod = cache[key];
|
const mod = cache[key];
|
||||||
if (!mod.loaded || !mod?.exports) continue;
|
if (!mod?.loaded || mod.exports == null) continue;
|
||||||
|
|
||||||
if (filter(mod.exports))
|
if (filter(mod.exports))
|
||||||
ret.push(mod.exports);
|
ret.push(mod.exports);
|
||||||
else if (typeof mod.exports !== "object")
|
|
||||||
|
if (typeof mod.exports !== "object")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mod.exports.default && filter(mod.exports.default))
|
for (const nestedMod in mod.exports) {
|
||||||
ret.push(mod.exports.default);
|
|
||||||
else for (const nestedMod in mod.exports) {
|
|
||||||
const nested = mod.exports[nestedMod];
|
const nested = mod.exports[nestedMod];
|
||||||
if (nested && filter(nested)) ret.push(nested);
|
if (nested && filter(nested)) ret.push(nested);
|
||||||
}
|
}
|
||||||
|
@ -204,7 +233,7 @@ export const findBulk = traceFunction("findBulk", function findBulk(...filterFns
|
||||||
outer:
|
outer:
|
||||||
for (const key in cache) {
|
for (const key in cache) {
|
||||||
const mod = cache[key];
|
const mod = cache[key];
|
||||||
if (!mod.loaded || !mod?.exports) continue;
|
if (!mod?.loaded || mod.exports == null) continue;
|
||||||
|
|
||||||
for (let j = 0; j < length; j++) {
|
for (let j = 0; j < length; j++) {
|
||||||
const filter = filters[j];
|
const filter = filters[j];
|
||||||
|
@ -221,13 +250,6 @@ export const findBulk = traceFunction("findBulk", function findBulk(...filterFns
|
||||||
if (typeof mod.exports !== "object")
|
if (typeof mod.exports !== "object")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mod.exports.default && filter(mod.exports.default)) {
|
|
||||||
results[j] = mod.exports.default;
|
|
||||||
filters[j] = undefined;
|
|
||||||
if (++found === length) break outer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const nestedMod in mod.exports) {
|
for (const nestedMod in mod.exports) {
|
||||||
const nested = mod.exports[nestedMod];
|
const nested = mod.exports[nestedMod];
|
||||||
if (nested && filter(nested)) {
|
if (nested && filter(nested)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue