Merge branch 'dev' of https://github.com/Vendicated/Vencord into discord-types

This commit is contained in:
ryan-0324 2024-08-10 13:12:51 -04:00
commit 1ae49f4d5b
6 changed files with 95 additions and 49 deletions

View file

@ -21,9 +21,9 @@ import esbuild from "esbuild";
import { readdir } from "fs/promises"; import { readdir } from "fs/promises";
import { join } from "path"; import { join } from "path";
import { BUILD_TIMESTAMP, commonOpts, disposeAll, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, rebuildAll, resolvePluginName, VERSION, watch, watchAll } from "./common.mjs"; import { BUILD_TIMESTAMP, commonOpts, commonRendererPlugins, disposeAll, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, rebuildAll, resolvePluginName, VERSION, watch, watchAll } from "./common.mjs";
/** @type {Record<string, any>} */ /** @type {Record<string, string>} */
const defines = { const defines = {
IS_STANDALONE: IS_STANDALONE.toString(), IS_STANDALONE: IS_STANDALONE.toString(),
IS_DEV: IS_DEV.toString(), IS_DEV: IS_DEV.toString(),
@ -35,7 +35,7 @@ const defines = {
BUILD_TIMESTAMP: BUILD_TIMESTAMP.toString() BUILD_TIMESTAMP: BUILD_TIMESTAMP.toString()
}; };
if (defines.IS_STANDALONE === false) if (defines.IS_STANDALONE === "false")
// If this is a local build (not standalone), optimize // If this is a local build (not standalone), optimize
// for the specific platform we're on // for the specific platform we're on
defines["process.platform"] = JSON.stringify(process.platform); defines["process.platform"] = JSON.stringify(process.platform);
@ -129,7 +129,7 @@ const contexts = await Promise.all([
sourcemap, sourcemap,
plugins: [ plugins: [
globPlugins("discordDesktop"), globPlugins("discordDesktop"),
...commonOpts.plugins ...commonRendererPlugins
], ],
define: { define: {
...defines, ...defines,
@ -177,7 +177,7 @@ const contexts = await Promise.all([
sourcemap, sourcemap,
plugins: [ plugins: [
globPlugins("vencordDesktop"), globPlugins("vencordDesktop"),
...commonOpts.plugins ...commonRendererPlugins
], ],
define: { define: {
...defines, ...defines,

View file

@ -24,7 +24,7 @@ import { join } from "path";
// @ts-expect-error: No types // @ts-expect-error: No types
import Zip from "zip-local"; import Zip from "zip-local";
import { BUILD_TIMESTAMP, commonOpts, disposeAll, globPlugins, IS_DEV, IS_REPORTER, rebuildAll, VERSION, watch, watchAll } from "./common.mjs"; import { BUILD_TIMESTAMP, commonOpts, commonRendererPlugins, disposeAll, globPlugins, IS_DEV, IS_REPORTER, rebuildAll, VERSION, watch, watchAll } from "./common.mjs";
/** @satisfies {esbuild.BuildOptions} */ /** @satisfies {esbuild.BuildOptions} */
const commonOptions = { const commonOptions = {
@ -35,7 +35,7 @@ const commonOptions = {
external: ["~plugins", "~git-hash", "/assets/*"], external: ["~plugins", "~git-hash", "/assets/*"],
plugins: [ plugins: [
globPlugins("web"), globPlugins("web"),
...commonOpts.plugins, ...commonRendererPlugins
], ],
target: ["esnext"], target: ["esnext"],
define: { define: {

View file

@ -24,6 +24,7 @@ import esbuild from "esbuild";
import { constants as FsConstants, readFileSync } from "fs"; import { constants as FsConstants, readFileSync } from "fs";
import { access, readdir, readFile } from "fs/promises"; import { access, readdir, readFile } from "fs/promises";
import { minify as minifyHtml } from "html-minifier-terser"; import { minify as minifyHtml } from "html-minifier-terser";
import { builtinModules } from "module";
import { join, relative } from "path"; import { join, relative } from "path";
import { promisify } from "util"; import { promisify } from "util";
@ -301,6 +302,20 @@ export const rebuildAll = contexts =>
/** @param {esbuild.BuildContext[]} contexts */ /** @param {esbuild.BuildContext[]} contexts */
export const watchAll = contexts => Promise.all(contexts.map(ctx => ctx.watch())); export const watchAll = contexts => Promise.all(contexts.map(ctx => ctx.watch()));
/**
* @param {RegExp} filter
* @param {string} message
* @returns {esbuild.Plugin}
*/
export const banImportPlugin = (filter, message) => ({
name: "ban-imports",
setup: build => {
build.onResolve({ filter }, () => {
return { errors: [{ text: message }] };
});
}
});
/** @satisfies {esbuild.BuildOptions} */ /** @satisfies {esbuild.BuildOptions} */
export const commonOpts = { export const commonOpts = {
// Does not work with esbuild.BuildContext.rebuild: https://github.com/evanw/esbuild/issues/2886#issuecomment-1416397046 // Does not work with esbuild.BuildContext.rebuild: https://github.com/evanw/esbuild/issues/2886#issuecomment-1416397046
@ -319,3 +334,15 @@ export const commonOpts = {
// Work around https://github.com/evanw/esbuild/issues/2460 // Work around https://github.com/evanw/esbuild/issues/2460
tsconfig: "./scripts/build/tsconfig.esbuild.json" tsconfig: "./scripts/build/tsconfig.esbuild.json"
}; };
const escapedBuiltinModules = builtinModules
.map(m => m.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"))
.join("|");
const builtinModuleRegex = new RegExp(`^(node:)?(${escapedBuiltinModules})$`);
export const commonRendererPlugins = [
banImportPlugin(builtinModuleRegex, "Cannot import node inbuilt modules in browser code. You need to use a native.ts file"),
banImportPlugin(/^react$/, "Cannot import from react. React and hooks should be imported from @webpack/common"),
banImportPlugin(/^electron(\/.*)?$/, "Cannot import electron in browser code. You need to use a native.ts file"),
...commonOpts.plugins
];

View file

@ -21,8 +21,7 @@ import { Devs } from "@utils/constants";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import type { GroupDMChannelRecord, UserRecord } from "@vencord/discord-types"; import type { GroupDMChannelRecord, UserRecord } from "@vencord/discord-types";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, UserStore, UserUtils } from "@webpack/common"; import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, useMemo, UserStore, UserUtils } from "@webpack/common";
import type { ReactElement } from "react";
const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel"); const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel");
@ -42,9 +41,27 @@ function getGroupDMName(channel: GroupDMChannelRecord) {
return names.join(", "); return names.join(", ");
} }
const useMutualGroupDMs = (userId: string) => useMemo(
() => ChannelStore.getSortedPrivateChannels()
.filter((c): c is GroupDMChannelRecord => c.isGroupDM() && c.recipients.includes(userId)),
[userId]
);
const isBotOrMe = (user: UserRecord) => user.bot || user.id === UserStore.getCurrentUser()!.id;
function getMutualGDMCountText(user: UserRecord) {
let count = 0;
for (const channel of Object.values(ChannelStore.getMutablePrivateChannels()))
if (channel.isGroupDM() && channel.recipients.includes(user.id))
count++;
return `${count === 0 ? "No" : count} Mutual Group${count !== 1 ? "s" : ""}`;
}
const IS_PATCHED = Symbol("MutualGroupDMs.Patched");
export default definePlugin({ export default definePlugin({
name: "MutualGroupDMs", name: "MutualGroupDMs",
description: "Shows mutual group dms in profiles", description: "Shows mutual group DMs in profiles",
authors: [Devs.amia], authors: [Devs.amia],
patches: [ patches: [
@ -66,8 +83,8 @@ export default definePlugin({
find: ".MUTUAL_FRIENDS?(", find: ".MUTUAL_FRIENDS?(",
replacement: [ replacement: [
{ {
match: /(?<=onItemSelect:\i,children:)(\i)\.map/, match: /\i\.useEffect.{0,100}(\i)\[0\]\.section/,
replace: "[...$1, ...($self.isBotOrMe(arguments[0].user) ? [] : [{section:'MUTUAL_GDMS',text:$self.getMutualGDMCountText(arguments[0].user)}])].map" replace: "$self.pushSection($1, arguments[0].user);$&"
}, },
{ {
match: /\(0,\i\.jsx\)\(\i,\{items:\i,section:(\i)/, match: /\(0,\i\.jsx\)\(\i,\{items:\i,section:(\i)/,
@ -77,21 +94,23 @@ export default definePlugin({
} }
], ],
isBotOrMe: (user: UserRecord) => user.bot || user.id === UserStore.getCurrentUser()!.id, isBotOrMe,
getMutualGDMCountText,
getMutualGDMCountText(user: UserRecord) { pushSection(sections: any[] & { [IS_PATCHED]?: true; }, user: UserRecord) {
let count = 0; if (isBotOrMe(user) || sections[IS_PATCHED]) return;
for (const channel of Object.values(ChannelStore.getMutablePrivateChannels()))
if (channel.isGroupDM() && channel.recipients.includes(user.id)) sections[IS_PATCHED] = true;
count++; sections.push({
return `${count === 0 ? "No" : count} Mutual Group${count === 1 ? "" : "s"}`; section: "MUTUAL_GDMS",
text: getMutualGDMCountText(user)
});
}, },
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: UserRecord; onClose: () => void; }) => { renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: UserRecord; onClose: () => void; }) => {
const entries: ReactElement[] = []; const mutualGroupDMs = useMutualGroupDMs(user.id);
for (const channel of ChannelStore.getSortedPrivateChannels())
if (channel.isGroupDM() && channel.recipients.includes(user.id)) const entries = mutualGroupDMs.map(channel => (
entries.push(
<Clickable <Clickable
className={ProfileListClasses.listRow} className={ProfileListClasses.listRow}
onClick={() => { onClick={() => {
@ -109,7 +128,7 @@ export default definePlugin({
<div className={GuildLabelClasses.guildNick}>{channel.recipients.length + 1} Members</div> <div className={GuildLabelClasses.guildNick}>{channel.recipients.length + 1} Members</div>
</div> </div>
</Clickable> </Clickable>
); ));
return ( return (
<ScrollerThin <ScrollerThin

View file

@ -24,13 +24,13 @@ const settings = definePluginSettings({
export default definePlugin({ export default definePlugin({
name: "PictureInPicture", name: "PictureInPicture",
description: "Adds picture in picture to videos (next to the Download button)", description: "Adds picture in picture to videos (next to the Download button)",
authors: [Devs.Nobody], authors: [Devs.Lumap],
settings, settings,
patches: [ patches: [
{ {
find: ".nonMediaMosaicItem]", find: ".removeMosaicItemHoverButton),",
replacement: { replacement: {
match: /\.nonMediaMosaicItem\]:!(\i).{0,50}?children:\[(\S)/, match: /\.nonMediaMosaicItem\]:!(\i).{0,50}?children:\[\S,(\S)/,
replace: "$&,$1&&$2&&$self.renderPiPButton()," replace: "$&,$1&&$2&&$self.renderPiPButton(),"
}, },
}, },

View file

@ -33,10 +33,6 @@ export interface Dev {
* If you are fine with attribution but don't want the badge, add badge: false * If you are fine with attribution but don't want the badge, add badge: false
*/ */
export const Devs = /* #__PURE__*/ Object.freeze({ export const Devs = /* #__PURE__*/ Object.freeze({
Nobody: {
name: "Nobody",
id: 0n,
},
Ven: { Ven: {
name: "Vee", name: "Vee",
id: 343383572805058560n id: 343383572805058560n
@ -545,7 +541,11 @@ export const Devs = /* #__PURE__*/ Object.freeze({
surgedevs: { surgedevs: {
name: "Chloe", name: "Chloe",
id: 1084592643784331324n id: 1084592643784331324n
} },
Lumap: {
name: "Lumap",
id: 585278686291427338n,
},
} satisfies Record<string, Dev>); } satisfies Record<string, Dev>);
// iife so #__PURE__ works correctly // iife so #__PURE__ works correctly