Compare commits

...

6 commits

Author SHA1 Message Date
b1559dd519
Merge remote-tracking branch 'upstream/main' 2024-08-14 14:30:30 -04:00
Nuckyz
4301ed889d
Fix ShowHiddenThings feature & PauseInvitesForever 2024-08-13 01:51:18 -03:00
Joona
1a712e75a6
fix(SpotifyControls): sync with external shuffle toggles (#2767)
Co-authored-by: v <vendicated@riseup.net>
2024-08-10 16:35:21 +00:00
Vendicated
87e6fa8647
build: improve errors when breaking module boundaries 2024-08-10 17:25:47 +02:00
Lumap
003e4a08d5
fix PictureInPicture (#2773)
Co-authored-by: v <vendicated@riseup.net>
2024-08-10 16:39:33 +02:00
Vendicated
4e3c178043
fix MutualGroupDMs 2024-08-10 16:35:11 +02:00
10 changed files with 88 additions and 41 deletions

View file

@ -21,7 +21,7 @@ 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, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, watch } from "./common.mjs"; import { BUILD_TIMESTAMP, commonOpts, exists, globPlugins, IS_DEV, IS_REPORTER, IS_STANDALONE, IS_UPDATER_DISABLED, resolvePluginName, VERSION, commonRendererPlugins, watch } from "./common.mjs";
const defines = { const defines = {
IS_STANDALONE, IS_STANDALONE,
@ -131,7 +131,7 @@ await Promise.all([
sourcemap, sourcemap,
plugins: [ plugins: [
globPlugins("discordDesktop"), globPlugins("discordDesktop"),
...commonOpts.plugins ...commonRendererPlugins
], ],
define: { define: {
...defines, ...defines,
@ -180,7 +180,7 @@ await Promise.all([
sourcemap, sourcemap,
plugins: [ plugins: [
globPlugins("vencordDesktop"), globPlugins("vencordDesktop"),
...commonOpts.plugins ...commonRendererPlugins
], ],
define: { define: {
...defines, ...defines,

View file

@ -23,7 +23,7 @@ import { appendFile, mkdir, readdir, readFile, rm, writeFile } from "fs/promises
import { join } from "path"; import { join } from "path";
import Zip from "zip-local"; import Zip from "zip-local";
import { BUILD_TIMESTAMP, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION } from "./common.mjs"; import { BUILD_TIMESTAMP, commonOpts, globPlugins, IS_DEV, IS_REPORTER, VERSION, commonRendererPlugins } from "./common.mjs";
/** /**
* @type {esbuild.BuildOptions} * @type {esbuild.BuildOptions}
@ -36,7 +36,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: {
@ -116,7 +116,12 @@ await Promise.all(
} }
}) })
] ]
); ).catch(err => {
console.error("Build failed");
console.error(err.message);
if (!commonOpts.watch)
process.exit(1);
});;
/** /**
* @type {(dir: string) => Promise<string[]>} * @type {(dir: string) => Promise<string[]>}

View file

@ -28,6 +28,7 @@ import { join, relative } from "path";
import { promisify } from "util"; import { promisify } from "util";
import { getPluginTarget } from "../utils.mjs"; import { getPluginTarget } from "../utils.mjs";
import { builtinModules } from "module";
/** @type {import("../../package.json")} */ /** @type {import("../../package.json")} */
const PackageJSON = JSON.parse(readFileSync("package.json")); const PackageJSON = JSON.parse(readFileSync("package.json"));
@ -292,6 +293,18 @@ export const stylePlugin = {
} }
}; };
/**
* @type {(filter: RegExp, message: string) => import("esbuild").Plugin}
*/
export const banImportPlugin = (filter, message) => ({
name: "ban-imports",
setup: build => {
build.onResolve({ filter }, () => {
return { errors: [{ text: message }] };
});
}
});
/** /**
* @type {import("esbuild").BuildOptions} * @type {import("esbuild").BuildOptions}
*/ */
@ -311,3 +324,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,7 +21,7 @@ import { Devs } from "@utils/constants";
import { isNonNullish } from "@utils/guards"; import { isNonNullish } from "@utils/guards";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findByPropsLazy } from "@webpack"; import { findByPropsLazy } from "@webpack";
import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, UserStore } from "@webpack/common"; import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, useMemo, UserStore } from "@webpack/common";
import { Channel, User } from "discord-types/general"; import { Channel, User } from "discord-types/general";
const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel"); const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel");
@ -39,6 +39,19 @@ function getGroupDMName(channel: Channel) {
.join(", "); .join(", ");
} }
const getMutualGroupDms = (userId: string) =>
ChannelStore.getSortedPrivateChannels()
.filter(c => c.isGroupDM() && c.recipients.includes(userId));
const isBotOrSelf = (user: User) => user.bot || user.id === UserStore.getCurrentUser().id;
function getMutualGDMCountText(user: User) {
const count = getMutualGroupDms(user.id).length;
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",
@ -63,8 +76,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.isBotOrSelf(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)/,
@ -74,15 +87,23 @@ export default definePlugin({
} }
], ],
isBotOrSelf: (user: User) => user.bot || user.id === UserStore.getCurrentUser().id, isBotOrSelf,
getMutualGDMCountText,
getMutualGDMCountText: (user: User) => { pushSection(sections: any[], user: User) {
const count = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).length; if (isBotOrSelf(user) || sections[IS_PATCHED]) return;
return `${count === 0 ? "No" : count} Mutual Group${count !== 1 ? "s" : ""}`;
sections[IS_PATCHED] = true;
sections.push({
section: "MUTUAL_GDMS",
text: getMutualGDMCountText(user)
});
}, },
renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => { renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => {
const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => ( const mutualDms = useMemo(() => getMutualGroupDms(user.id), [user.id]);
const entries = mutualDms.map(c => (
<Clickable <Clickable
className={ProfileListClasses.listRow} className={ProfileListClasses.listRow}
onClick={() => { onClick={() => {

View file

@ -19,16 +19,11 @@
import ErrorBoundary from "@components/ErrorBoundary"; 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 { findLazy } from "@webpack";
import { Constants, GuildStore, i18n, RestAPI } from "@webpack/common"; import { Constants, GuildStore, i18n, RestAPI } from "@webpack/common";
const InvitesDisabledExperiment = findLazy(m => m.definition?.id === "2022-07_invites_disabled");
function showDisableInvites(guildId: string) { function showDisableInvites(guildId: string) {
// Once the experiment is removed, this should keep working
const { enableInvitesDisabled } = InvitesDisabledExperiment?.getCurrentConfig?.({ guildId }) ?? { enableInvitesDisabled: true };
// @ts-ignore // @ts-ignore
return enableInvitesDisabled && !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED"); return !GuildStore.getGuild(guildId).hasFeature("INVITES_DISABLED");
} }
function disableInvites(guildId: string) { function disableInvites(guildId: string) {

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

@ -51,7 +51,7 @@ export default definePlugin({
}, },
}, },
{ {
find: "2022-07_invites_disabled", find: "INVITES_DISABLED))||",
predicate: () => settings.store.showInvitesPaused, predicate: () => settings.store.showInvitesPaused,
replacement: { replacement: {
match: /\i\.\i\.can\(\i\.\i.MANAGE_GUILD,\i\)/, match: /\i\.\i\.can\(\i\.\i.MANAGE_GUILD,\i\)/,

View file

@ -55,6 +55,7 @@ interface PlayerState {
// added by patch // added by patch
actual_repeat: Repeat; actual_repeat: Repeat;
shuffle: boolean;
} }
interface Device { interface Device {
@ -182,6 +183,7 @@ export const SpotifyStore = proxyLazyWebpack(() => {
store.isPlaying = e.isPlaying ?? false; store.isPlaying = e.isPlaying ?? false;
store.volume = e.volumePercent ?? 0; store.volume = e.volumePercent ?? 0;
store.repeat = e.actual_repeat || "off"; store.repeat = e.actual_repeat || "off";
store.shuffle = e.shuffle ?? false;
store.position = e.position ?? 0; store.position = e.position ?? 0;
store.isSettingPosition = false; store.isSettingPosition = false;
store.emitChange(); store.emitChange();

View file

@ -70,21 +70,20 @@ export default definePlugin({
replace: "false", replace: "false",
}] }]
}, },
// Discord doesn't give you the repeat kind, only a boolean
{ {
find: 'repeat:"off"!==', find: 'repeat:"off"!==',
replacement: { replacement: [
match: /repeat:"off"!==(.{1,3}),/, {
replace: "actual_repeat:$1,$&" // Discord doesn't give you shuffle state and the repeat kind, only a boolean
} match: /repeat:"off"!==(\i),/,
replace: "shuffle:arguments[2]?.shuffle_state??false,actual_repeat:$1,$&"
}, },
{ {
find: "artists.filter",
replacement: {
match: /(?<=artists.filter\(\i=>).{0,10}\i\.id\)&&/, match: /(?<=artists.filter\(\i=>).{0,10}\i\.id\)&&/,
replace: "" replace: ""
} }
} ]
},
], ],
start: () => toggleHoverControls(Settings.plugins.SpotifyControls.hoverControls), start: () => toggleHoverControls(Settings.plugins.SpotifyControls.hoverControls),

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