Merge branch 'dev' into main

This commit is contained in:
byeoon 2024-05-07 07:53:47 -04:00 committed by GitHub
commit 720aaf6f3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 2552 additions and 2098 deletions

View file

@ -18,14 +18,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 19
uses: actions/setup-node@v3
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 19
node-version: 20
cache: "pnpm"
- name: Install dependencies

View file

@ -13,7 +13,7 @@ jobs:
if: github.repository == 'Vendicated/Vencord'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pixta-dev/repository-mirroring-action@674e65a7d483ca28dafaacba0d07351bdcc8bd75 # v1.1.1

View file

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: check that tag matches package.json version
run: |
@ -20,12 +20,12 @@ jobs:
exit 1
fi
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 19
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 19
node-version: 20
cache: "pnpm"
- name: Install dependencies

View file

@ -21,10 +21,10 @@ jobs:
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 18
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: "pnpm"
- name: Install dependencies
@ -35,7 +35,7 @@ jobs:
id: setup-chrome
uses: browser-actions/setup-chrome@82b9ce628cc5595478a9ebadc480958a36457dc2
with:
chrome-version: stable
chrome-version: stable
- name: Build web
run: pnpm buildWeb --standalone --dev

View file

@ -10,13 +10,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3 # Install pnpm using packageManager key in package.json
- name: Use Node.js 18
uses: actions/setup-node@v3
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: "pnpm"
- name: Install dependencies

View file

@ -1,7 +1,7 @@
{
"name": "vencord",
"private": "true",
"version": "1.8.0",
"version": "1.8.1",
"description": "The cutest Discord client mod",
"homepage": "https://github.com/Vendicated/Vencord#readme",
"bugs": {
@ -71,7 +71,7 @@
"zip-local": "^0.3.5",
"zustand": "^3.7.2"
},
"packageManager": "pnpm@8.10.2",
"packageManager": "pnpm@9.1.0",
"pnpm": {
"patchedDependencies": {
"eslint-plugin-path-alias@1.0.0": "patches/eslint-plugin-path-alias@1.0.0.patch",

File diff suppressed because it is too large Load diff

View file

@ -25,10 +25,11 @@ import { access, readdir, readFile } from "fs/promises";
import { join, relative } from "path";
import { promisify } from "util";
// wtf is this assert syntax
import PackageJSON from "../../package.json" assert { type: "json" };
import { getPluginTarget } from "../utils.mjs";
/** @type {import("../../package.json")} */
const PackageJSON = JSON.parse(readFileSync("package.json"));
export const VERSION = PackageJSON.version;
// https://reproducible-builds.org/docs/source-date-epoch/
export const BUILD_TIMESTAMP = Number(process.env.SOURCE_DATE_EPOCH) || Date.now();

View file

@ -27,6 +27,7 @@ import PluginModal from "@components/PluginSettings/PluginModal";
import { AddonCard } from "@components/VencordSettings/AddonCard";
import { SettingsTab } from "@components/VencordSettings/shared";
import { ChangeList } from "@utils/ChangeList";
import { proxyLazy } from "@utils/lazy";
import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins";
import { classes, isObjectEmpty } from "@utils/misc";
@ -38,8 +39,8 @@ import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextI
import Plugins from "~plugins";
import { startDependenciesRecursive, startPlugin, stopPlugin } from "../../plugins";
// Avoid circular dependency
const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins"));
const cl = classNameFactory("vc-plugins-");
const logger = new Logger("PluginSettings", "#a6d189");

View file

@ -23,6 +23,7 @@ import DonateButton from "@components/DonateButton";
import ErrorBoundary from "@components/ErrorBoundary";
import { Flex } from "@components/Flex";
import { Heart } from "@components/Heart";
import { openContributorModal } from "@components/PluginSettings/ContributorModal";
import { Devs } from "@utils/constants";
import { Margins } from "@utils/margins";
import { isPluginDev } from "@utils/misc";
@ -37,12 +38,7 @@ const ContributorBadge: ProfileBadge = {
image: CONTRIBUTOR_BADGE,
position: BadgePosition.START,
shouldShow: ({ user }) => isPluginDev(user.id),
onClick(_, { user }) {
// circular import shenanigans
const { openContributorModal } = require("@components/PluginSettings/ContributorModal") as typeof import("@components/PluginSettings/ContributorModal");
// setImmediate is needed to run on later tick to workaround limitation in proxyLazy
setImmediate(() => openContributorModal(user));
}
onClick: (_, { user }) => openContributorModal(user)
};
let DonorBadges = {} as Record<string, Array<Record<"tooltip" | "badge", string>>>;

View file

@ -17,6 +17,13 @@
*/
import { Settings } from "@api/Settings";
import BackupAndRestoreTab from "@components/VencordSettings/BackupAndRestoreTab";
import CloudTab from "@components/VencordSettings/CloudTab";
import PatchHelperTab from "@components/VencordSettings/PatchHelperTab";
import PluginsTab from "@components/VencordSettings/PluginsTab";
import ThemesTab from "@components/VencordSettings/ThemesTab";
import UpdaterTab from "@components/VencordSettings/UpdaterTab";
import VencordTab from "@components/VencordSettings/VencordTab";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { React } from "@webpack/common";
@ -36,7 +43,7 @@ export default definePlugin({
match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/,
replace: (m, component, props) => {
props = props.replace(/children:\[.+\]/, "");
return `${m},Vencord.Plugins.plugins.Settings.makeInfoElements(${component}, ${props})`;
return `${m},$self.makeInfoElements(${component}, ${props})`;
}
}
]
@ -77,43 +84,43 @@ export default definePlugin({
{
section: "VencordSettings",
label: "Vencord",
element: require("@components/VencordSettings/VencordTab").default,
element: VencordTab,
className: "vc-settings"
},
{
section: "VencordPlugins",
label: "Plugins",
element: require("@components/VencordSettings/PluginsTab").default,
element: PluginsTab,
className: "vc-plugins"
},
{
section: "VencordThemes",
label: "Themes",
element: require("@components/VencordSettings/ThemesTab").default,
element: ThemesTab,
className: "vc-themes"
},
!IS_UPDATER_DISABLED && {
section: "VencordUpdater",
label: "Updater",
element: require("@components/VencordSettings/UpdaterTab").default,
element: UpdaterTab,
className: "vc-updater"
},
{
section: "VencordCloud",
label: "Cloud",
element: require("@components/VencordSettings/CloudTab").default,
element: CloudTab,
className: "vc-cloud"
},
{
section: "VencordSettingsSync",
label: "Backup & Restore",
element: require("@components/VencordSettings/BackupAndRestoreTab").default,
element: BackupAndRestoreTab,
className: "vc-backup-restore"
},
IS_DEV && {
section: "VencordPatchHelper",
label: "Patch Helper",
element: require("@components/VencordSettings/PatchHelperTab").default,
element: PatchHelperTab,
className: "vc-patch-helper"
},
...this.customSections.map(func => func(SectionTypes)),

View file

@ -20,10 +20,12 @@ import { definePluginSettings } from "@api/Settings";
import ErrorBoundary from "@components/ErrorBoundary";
import { ErrorCard } from "@components/ErrorCard";
import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import { Margins } from "@utils/margins";
import definePlugin, { OptionType } from "@utils/types";
import { findByPropsLazy } from "@webpack";
import { Forms, React } from "@webpack/common";
import { Forms, React, UserStore } from "@webpack/common";
import { User } from "discord-types/general";
const KbdStyles = findByPropsLazy("key", "removeBuildOverride");
@ -68,8 +70,8 @@ export default definePlugin({
predicate: () => settings.store.enableIsStaff,
replacement: [
{
match: /=>*?(\i)\.hasFlag\((\i\.\i)\.STAFF\)}/,
replace: (_, user, flags) => `=>Vencord.Webpack.Common.UserStore.getCurrentUser()?.id===${user}.id||${user}.hasFlag(${flags}.STAFF)}`
match: /(?<=>)(\i)\.hasFlag\((\i\.\i)\.STAFF\)(?=})/,
replace: (_, user, flags) => `$self.isStaff(${user},${flags})`
},
{
match: /hasFreePremium\(\){return this.isStaff\(\)\s*?\|\|/,
@ -86,6 +88,15 @@ export default definePlugin({
}
],
isStaff(user: User, flags: any) {
try {
return UserStore.getCurrentUser()?.id === user.id || user.hasFlag(flags.STAFF);
} catch (err) {
new Logger("Experiments").error(err);
return user.hasFlag(flags.STAFF);
}
},
settingsAboutComponent: () => {
const isMacOS = navigator.platform.includes("Mac");
const modKey = isMacOS ? "cmd" : "ctrl";

View file

@ -166,10 +166,13 @@ const settings = definePluginSettings({
description: "What text the hyperlink should use. {{NAME}} will be replaced with the emoji/sticker name.",
type: OptionType.STRING,
default: "{{NAME}}"
},
disableEmbedPermissionCheck: {
description: "Whether to disable the embed permission check when sending fake emojis and stickers",
type: OptionType.BOOLEAN,
default: false
}
}).withPrivateSettings<{
disableEmbedPermissionCheck: boolean;
}>();
});
function hasPermission(channelId: string, permission: bigint) {
const channel = ChannelStore.getChannel(channelId);
@ -397,6 +400,14 @@ export default definePlugin({
match: /(?<=type:"(?:SOUNDBOARD_SOUNDS_RECEIVED|GUILD_SOUNDBOARD_SOUND_CREATE|GUILD_SOUNDBOARD_SOUND_UPDATE|GUILD_SOUNDBOARD_SOUNDS_UPDATE)".+?available:)\i\.available/g,
replace: "true"
}
},
// Allow using custom notification sounds
{
find: "canUseCustomNotificationSounds:function",
replacement: {
match: /canUseCustomNotificationSounds:function\(\i\){/,
replace: "$&return true;"
}
}
],
@ -413,31 +424,35 @@ export default definePlugin({
},
handleProtoChange(proto: any, user: any) {
if (proto == null || typeof proto === "string" || !UserSettingsProtoStore || !PreloadedUserSettingsActionCreators || !AppearanceSettingsActionCreators || !ClientThemeSettingsActionsCreators) return;
try {
if (proto == null || typeof proto === "string") return;
const premiumType: number = user?.premium_type ?? UserStore?.getCurrentUser()?.premiumType ?? 0;
const premiumType: number = user?.premium_type ?? UserStore?.getCurrentUser()?.premiumType ?? 0;
if (premiumType !== 2) {
proto.appearance ??= AppearanceSettingsActionCreators.create();
if (premiumType !== 2) {
proto.appearance ??= AppearanceSettingsActionCreators.create();
if (UserSettingsProtoStore.settings.appearance?.theme != null) {
const appearanceSettingsDummy = AppearanceSettingsActionCreators.create({
theme: UserSettingsProtoStore.settings.appearance.theme
});
if (UserSettingsProtoStore.settings.appearance?.theme != null) {
const appearanceSettingsDummy = AppearanceSettingsActionCreators.create({
theme: UserSettingsProtoStore.settings.appearance.theme
});
proto.appearance.theme = appearanceSettingsDummy.theme;
}
if (UserSettingsProtoStore.settings.appearance?.clientThemeSettings?.backgroundGradientPresetId?.value != null) {
const clientThemeSettingsDummy = ClientThemeSettingsActionsCreators.create({
backgroundGradientPresetId: {
value: UserSettingsProtoStore.settings.appearance.clientThemeSettings.backgroundGradientPresetId.value
}
});
proto.appearance.clientThemeSettings ??= clientThemeSettingsDummy;
proto.appearance.clientThemeSettings.backgroundGradientPresetId = clientThemeSettingsDummy.backgroundGradientPresetId;
proto.appearance.theme = appearanceSettingsDummy.theme;
}
if (UserSettingsProtoStore.settings.appearance?.clientThemeSettings?.backgroundGradientPresetId?.value != null) {
const clientThemeSettingsDummy = ClientThemeSettingsActionsCreators.create({
backgroundGradientPresetId: {
value: UserSettingsProtoStore.settings.appearance.clientThemeSettings.backgroundGradientPresetId.value
}
});
proto.appearance.clientThemeSettings ??= clientThemeSettingsDummy;
proto.appearance.clientThemeSettings.backgroundGradientPresetId = clientThemeSettingsDummy.backgroundGradientPresetId;
}
}
} catch (err) {
new Logger("FakeNitro").error(err);
}
},

View file

@ -10,15 +10,15 @@ import definePlugin from "@utils/types";
export default definePlugin({
name: "ImageLink",
description: "Never hide image links in messages, even if it's the only content",
authors: [Devs.Kyuuhachi],
authors: [Devs.Kyuuhachi, Devs.Sqaaakoi],
patches: [
{
find: "isEmbedInline:function()",
find: "unknownUserMentionPlaceholder:",
replacement: {
match: /(?<=isEmbedInline:function\(\)\{return )\i(?=\})/,
replace: "()=>false",
},
},
],
match: /\(0,\i\.isEmbedInline\)\(\i\)/,
replace: "false",
}
}
]
});

View file

@ -19,11 +19,12 @@
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { findByProps, findStoreLazy } from "@webpack";
import { findByPropsLazy, findStoreLazy } from "@webpack";
import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common";
import { Settings } from "Vencord";
const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore");
const { FriendsSections } = findByPropsLazy("FriendsSections");
interface UserAffinity {
user_id: string;
@ -181,7 +182,6 @@ export default definePlugin({
},
start() {
const { FriendsSections } = findByProps("FriendsSections");
FriendsSections.IMPLICIT = "IMPLICIT";
}
});

View file

@ -36,6 +36,7 @@ export const patches = [] as Patch[];
/** Whether we have subscribed to flux events of all the enabled plugins when FluxDispatcher was ready */
let enabledPluginsSubscribedFlux = false;
const subscribedFluxEventsPlugins = new Set<string>();
const settings = Settings.plugins;
@ -123,7 +124,9 @@ export function startDependenciesRecursive(p: Plugin) {
}
export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof FluxDispatcher) {
if (p.flux) {
if (p.flux && !subscribedFluxEventsPlugins.has(p.name)) {
subscribedFluxEventsPlugins.add(p.name);
logger.debug("Subscribing to flux events of plugin", p.name);
for (const [event, handler] of Object.entries(p.flux)) {
fluxDispatcher.subscribe(event as FluxEvents, handler);
@ -133,6 +136,8 @@ export function subscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof Flux
export function unsubscribePluginFluxEvents(p: Plugin, fluxDispatcher: typeof FluxDispatcher) {
if (p.flux) {
subscribedFluxEventsPlugins.delete(p.name);
logger.debug("Unsubscribing from flux events of plugin", p.name);
for (const [event, handler] of Object.entries(p.flux)) {
fluxDispatcher.unsubscribe(event as FluxEvents, handler);

View file

@ -36,6 +36,7 @@ import { settings } from "./settings";
import { showToast } from "./utils";
const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => {
if (!guild) return;
children.push(
<Menu.MenuItem
label="View Reviews"

View file

@ -16,10 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { proxyLazy } from "@utils/lazy";
import type * as Stores from "discord-types/stores";
// eslint-disable-next-line path-alias/no-relative
import { findByPropsLazy } from "../webpack";
import { findByProps, findByPropsLazy } from "../webpack";
import { waitForStore } from "./internal";
import * as t from "./types/stores";
@ -67,20 +68,17 @@ export let DraftStore: t.DraftStore;
*
* @param stores The stores to listen to
* @param mapper A function that returns the data you need
* @param idk some thing, idk just pass null
* @param dependencies An array of reactive values which the hook depends on. Use this if your mapper or equality function depends on the value of another hook
* @param isEqual A custom comparator for the data returned by mapper
*
* @example const user = useStateFromStores([UserStore], () => UserStore.getCurrentUser(), null, (old, current) => old.id === current.id);
*/
export const { useStateFromStores }: {
useStateFromStores: <T>(
stores: t.FluxStore[],
mapper: () => T,
idk?: any,
isEqual?: (old: T, newer: T) => boolean
) => T;
}
= findByPropsLazy("useStateFromStores");
export const useStateFromStores = proxyLazy(() => findByProps("useStateFromStores").useStateFromStores) as <T>(
stores: t.FluxStore[],
mapper: () => T,
dependencies?: any,
isEqual?: (old: T, newer: T) => boolean
) => T;
waitForStore("DraftStore", s => DraftStore = s);
waitForStore("UserStore", s => UserStore = s);

View file

@ -63,7 +63,8 @@ Object.defineProperty(Function.prototype, "O", {
// When using react devtools or other extensions, or even when discord loads the sentry, we may also catch their webpack here.
// This ensures we actually got the right one
// this.e (wreq.e) is the method for loading a chunk, and only the main webpack has it
if (new Error().stack?.includes("discord.com") && String(this.e).includes("Promise.all")) {
const { stack } = new Error();
if ((stack?.includes("discord.com") || stack?.includes("discordapp.com")) && String(this.e).includes("Promise.all")) {
logger.info("Found main WebpackRequire.onChunksLoaded");
delete (Function.prototype as any).O;
@ -120,9 +121,9 @@ Object.defineProperty(Function.prototype, "m", {
set(v: any) {
// When using react devtools or other extensions, we may also catch their webpack here.
// This ensures we actually got the right one
const error = new Error();
if (error.stack?.includes("discord.com")) {
logger.info("Found Webpack module factory", error.stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? "");
const { stack } = new Error();
if (stack?.includes("discord.com") || stack?.includes("discordapp.com")) {
logger.info("Found Webpack module factory", stack.match(/\/assets\/(.+?\.js)/)?.[1] ?? "");
patchFactories(v);
}

View file

@ -1,5 +1,6 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"skipLibCheck": true,