From 30e4e8315829bf9941adbf0cf1a386629af804d9 Mon Sep 17 00:00:00 2001 From: Maddie <52103563+maddie480@users.noreply.github.com> Date: Tue, 3 Sep 2024 03:53:03 +0200 Subject: [PATCH 01/52] NoServerEmojis: Fix detecting server emojis (#2835) --- src/plugins/noServerEmojis/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/noServerEmojis/index.ts b/src/plugins/noServerEmojis/index.ts index ed843769c..6a39f55ca 100644 --- a/src/plugins/noServerEmojis/index.ts +++ b/src/plugins/noServerEmojis/index.ts @@ -36,7 +36,7 @@ export default definePlugin({ } ], shouldSkip(guildId: string, emoji: any) { - if (emoji.type !== "GUILD_EMOJI") { + if (emoji.type !== 1) { return false; } if (settings.store.shownEmojis === "onlyUnicode") { From 7f784befc211abcc648463edc800bb7008fc5143 Mon Sep 17 00:00:00 2001 From: Ramzi Al Haddad Date: Tue, 3 Sep 2024 05:50:25 -0500 Subject: [PATCH 02/52] SecretRingToneEnabler: Option to always play Snow Halation Theme (#2831) --- src/plugins/secretRingTone/index.ts | 35 +++++++++++++++++++++-------- src/utils/constants.ts | 4 ++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/plugins/secretRingTone/index.ts b/src/plugins/secretRingTone/index.ts index be804efc4..f2913afd1 100644 --- a/src/plugins/secretRingTone/index.ts +++ b/src/plugins/secretRingTone/index.ts @@ -4,21 +4,38 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; -import definePlugin from "@utils/types"; +import definePlugin, { OptionType } from "@utils/types"; + +const settings = definePluginSettings({ + onlySnow: { + type: OptionType.BOOLEAN, + description: "Only play the Snow Halation Theme", + default: false, + restartNeeded: true + } +}); -// NOTE - Ultimately should probably be turned into a ringtone picker plugin export default definePlugin({ name: "SecretRingToneEnabler", description: "Always play the secret version of the discord ringtone (except during special ringtone events)", - authors: [Devs.AndrewDLO, Devs.FieryFlames], + authors: [Devs.AndrewDLO, Devs.FieryFlames, Devs.RamziAH], + settings, patches: [ { find: '"call_ringing_beat"', - replacement: { - match: /500!==\i\(\)\.random\(1,1e3\)/, - replace: "false", - } - }, - ], + replacement: [ + { + match: /500!==\i\(\)\.random\(1,1e3\)/, + replace: "false" + }, + { + predicate: () => settings.store.onlySnow, + match: /"call_ringing_beat",/, + replace: "" + } + ] + } + ] }); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 7fb2b6bf0..b0ad77fb1 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -566,6 +566,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "niko", id: 341377368075796483n, }, + RamziAH: { + name: "RamziAH", + id: 1279957227612147747n, + }, } satisfies Record); // iife so #__PURE__ works correctly From d10e649b63ec46a511cd70f684ac9a7fbfaf8f52 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Wed, 4 Sep 2024 07:04:17 -0400 Subject: [PATCH 03/52] VolumeBooster: Fix playing sound in wrong output device (#2840) --- src/plugins/volumeBooster/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/volumeBooster/index.ts b/src/plugins/volumeBooster/index.ts index 02a955a80..490bf62c2 100644 --- a/src/plugins/volumeBooster/index.ts +++ b/src/plugins/volumeBooster/index.ts @@ -39,7 +39,7 @@ interface StreamData { gainNode?: GainNode, id: string, levelNode: AudioWorkletNode, - sinkId: string, + sinkId: string | "default", stream: MediaStream, streamSourceNode?: MediaStreamAudioSourceNode, videoStreamId: string, @@ -128,6 +128,12 @@ export default definePlugin({ gain.connect(data.audioContext.destination); } + // @ts-expect-error + if (data.sinkId != null && data.sinkId !== data.audioContext.sinkId && "setSinkId" in AudioContext.prototype) { + // @ts-expect-error https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/setSinkId + data.audioContext.setSinkId(data.sinkId); + } + data.gainNode.gain.value = data._mute ? 0 : data._volume / 100; From df8aec8e3c5e4d13bc2f2df4e125ee3205c4d185 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 4 Sep 2024 08:24:54 -0300 Subject: [PATCH 04/52] Fix BetterFolders and FriendsSince --- src/plugins/_api/serverList.ts | 2 +- src/plugins/betterFolders/index.tsx | 4 ++-- src/plugins/friendsSince/index.tsx | 33 +++++++---------------------- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/plugins/_api/serverList.ts b/src/plugins/_api/serverList.ts index f45bbf104..7904e78b0 100644 --- a/src/plugins/_api/serverList.ts +++ b/src/plugins/_api/serverList.ts @@ -34,7 +34,7 @@ export default definePlugin({ { find: "Messages.SERVERS,children", replacement: { - match: /(?<=Messages\.SERVERS,children:).+?default:return null\}\}\)/, + match: /(?<=Messages\.SERVERS,children:)\i\.map\(\i\)/, replace: "Vencord.Api.ServerList.renderAll(Vencord.Api.ServerList.ServerListRenderPosition.In).concat($&)" } } diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 072f4ee66..0bef0933d 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -132,8 +132,8 @@ export default definePlugin({ }, // Export the isBetterFolders variable to the folders component { - match: /(?<=\.Messages\.SERVERS.+?switch\((\i)\.type\){case \i\.\i\.FOLDER:.+?folderNode:\i,)/, - replace: 'isBetterFolders:typeof isBetterFolders!=="undefined"?isBetterFolders:false,' + match: /switch\(\i\.type\){case \i\.\i\.FOLDER:.+?folderNode:\i,/, + replace: '$&isBetterFolders:typeof isBetterFolders!=="undefined"?isBetterFolders:false,' } ] }, diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index 0399a2f72..cb5634c8e 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -7,16 +7,15 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; -import { Logger } from "@utils/Logger"; import definePlugin from "@utils/types"; -import { findByCodeLazy, findByPropsLazy, findLazy } from "@webpack"; -import { Heading, RelationshipStore, Text } from "@webpack/common"; +import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { RelationshipStore, Text } from "@webpack/common"; const containerWrapper = findByPropsLazy("memberSinceWrapper"); const container = findByPropsLazy("memberSince"); const getCreatedAtDate = findByCodeLazy('month:"short",day:"numeric"'); const locale = findByPropsLazy("getLocale"); -const section = findLazy((m: any) => m.section !== void 0 && m.heading !== void 0 && Object.values(m).length === 2); +const Section = findComponentByCodeLazy('"auto":"smooth"', ".section"); export default definePlugin({ name: "FriendsSince", @@ -28,7 +27,7 @@ export default definePlugin({ find: ".PANEL}),nicknameIcons", replacement: { match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id)}\)}\)/, - replace: "$&,$self.friendsSinceNew({userId:$1,isSidebar:true})" + replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:true})" } }, // User Profile Modal @@ -36,34 +35,19 @@ export default definePlugin({ find: "action:\"PRESS_APP_CONNECTION\"", replacement: { match: /USER_PROFILE_MEMBER_SINCE,.{0,100}userId:(\i\.id),.{0,100}}\)}\),/, - replace: "$&,$self.friendsSinceNew({userId:$1,isSidebar:false})," + replace: "$&,$self.FriendsSinceComponent({userId:$1,isSidebar:false})," } } ], - getFriendSince(userId: string) { - try { - if (!RelationshipStore.isFriend(userId)) return null; - - return RelationshipStore.getSince(userId); - } catch (err) { - new Logger("FriendsSince").error(err); - return null; - } - }, - - friendsSinceNew: ErrorBoundary.wrap(({ userId, isSidebar }: { userId: string; isSidebar: boolean; }) => { + FriendsSinceComponent: ErrorBoundary.wrap(({ userId, isSidebar }: { userId: string; isSidebar: boolean; }) => { if (!RelationshipStore.isFriend(userId)) return null; const friendsSince = RelationshipStore.getSince(userId); if (!friendsSince) return null; return ( -
- - Friends Since - - +
{ isSidebar ? ( @@ -91,8 +75,7 @@ export default definePlugin({ ) } - -
+
); }, { noop: true }), }); From 244cb26c328828503835c680fa294917cb7d5f9b Mon Sep 17 00:00:00 2001 From: ElectricSteve <96793824+electricsteve@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:00:49 +0200 Subject: [PATCH 05/52] Dearrow: Add option to not dearrow by default (#2818) --- src/plugins/dearrow/index.tsx | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/plugins/dearrow/index.tsx b/src/plugins/dearrow/index.tsx index 5fb438256..10175c846 100644 --- a/src/plugins/dearrow/index.tsx +++ b/src/plugins/dearrow/index.tsx @@ -46,7 +46,7 @@ const embedUrlRe = /https:\/\/www\.youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/; async function embedDidMount(this: Component) { try { const { embed } = this.props; - const { replaceElements } = settings.store; + const { replaceElements, dearrowByDefault } = settings.store; if (!embed || embed.dearrow || embed.provider?.name !== "YouTube" || !embed.video?.url) return; @@ -63,18 +63,22 @@ async function embedDidMount(this: Component) { if (!hasTitle && !hasThumb) return; + embed.dearrow = { - enabled: true + enabled: dearrowByDefault }; if (hasTitle && replaceElements !== ReplaceElements.ReplaceThumbnailsOnly) { - embed.dearrow.oldTitle = embed.rawTitle; - embed.rawTitle = titles[0].title.replace(/(^|\s)>(\S)/g, "$1$2"); - } + const replacementTitle = titles[0].title.replace(/(^|\s)>(\S)/g, "$1$2"); + embed.dearrow.oldTitle = dearrowByDefault ? embed.rawTitle : replacementTitle; + if (dearrowByDefault) embed.rawTitle = replacementTitle; + } if (hasThumb && replaceElements !== ReplaceElements.ReplaceTitlesOnly) { - embed.dearrow.oldThumb = embed.thumbnail.proxyURL; - embed.thumbnail.proxyURL = `https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=${videoId}&time=${thumbnails[0].timestamp}`; + const replacementProxyURL = `https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=${videoId}&time=${thumbnails[0].timestamp}`; + + embed.dearrow.oldThumb = dearrowByDefault ? embed.thumbnail.proxyURL : replacementProxyURL; + if (embed.thumbnail.proxyURL) embed.thumbnail.proxyURL = replacementProxyURL; } this.forceUpdate(); @@ -96,6 +100,7 @@ function DearrowButton({ component }: { component: Component; }) { className={"vc-dearrow-toggle-" + (embed.dearrow.enabled ? "on" : "off")} onClick={() => { const { enabled, oldThumb, oldTitle } = embed.dearrow; + settings.store.dearrowByDefault = !enabled; embed.dearrow.enabled = !enabled; if (oldTitle) { embed.dearrow.oldTitle = embed.rawTitle; @@ -153,6 +158,12 @@ const settings = definePluginSettings({ { label: "Titles", value: ReplaceElements.ReplaceTitlesOnly }, { label: "Thumbnails", value: ReplaceElements.ReplaceThumbnailsOnly }, ], + }, + dearrowByDefault: { + description: "Dearrow videos automatically", + type: OptionType.BOOLEAN, + default: true, + restartNeeded: false } }); From 7333f40db697bc5f06694a0b1d462468b0605529 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 4 Sep 2024 10:16:45 -0300 Subject: [PATCH 06/52] Dearrow: Fix thumbnails with default option --- src/plugins/dearrow/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/dearrow/index.tsx b/src/plugins/dearrow/index.tsx index 10175c846..b7e90e096 100644 --- a/src/plugins/dearrow/index.tsx +++ b/src/plugins/dearrow/index.tsx @@ -78,7 +78,7 @@ async function embedDidMount(this: Component) { const replacementProxyURL = `https://dearrow-thumb.ajay.app/api/v1/getThumbnail?videoID=${videoId}&time=${thumbnails[0].timestamp}`; embed.dearrow.oldThumb = dearrowByDefault ? embed.thumbnail.proxyURL : replacementProxyURL; - if (embed.thumbnail.proxyURL) embed.thumbnail.proxyURL = replacementProxyURL; + if (dearrowByDefault) embed.thumbnail.proxyURL = replacementProxyURL; } this.forceUpdate(); From 99cd423efbaf4da9c5d1c7bf23061d933eb99d18 Mon Sep 17 00:00:00 2001 From: Haruka <96925398+nakoyasha@users.noreply.github.com> Date: Thu, 5 Sep 2024 00:26:08 +0300 Subject: [PATCH 07/52] fix crashing on canary when searching slash commands (#2844) --- src/api/Commands/index.ts | 2 ++ src/api/Commands/types.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/api/Commands/index.ts b/src/api/Commands/index.ts index ef4db171c..5e3fc8f4d 100644 --- a/src/api/Commands/index.ts +++ b/src/api/Commands/index.ts @@ -138,6 +138,8 @@ export function registerCommand(command: C, plugin: string) { throw new Error(`Command '${command.name}' already exists.`); command.isVencordCommand = true; + command.untranslatedName ??= command.name; + command.untranslatedDescription ??= command.description; command.id ??= `-${BUILT_IN.length + 1}`; command.applicationId ??= "-1"; // BUILT_IN; command.type ??= ApplicationCommandType.CHAT_INPUT; diff --git a/src/api/Commands/types.ts b/src/api/Commands/types.ts index bd349e250..70b73775a 100644 --- a/src/api/Commands/types.ts +++ b/src/api/Commands/types.ts @@ -93,8 +93,10 @@ export interface Command { isVencordCommand?: boolean; name: string; + untranslatedName?: string; displayName?: string; description: string; + untranslatedDescription?: string; displayDescription?: string; options?: Option[]; From be02baffaa8c46d499b90c6e2f638e4fe7aa28bd Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 5 Sep 2024 02:12:09 +0200 Subject: [PATCH 08/52] MemberCount: fix null safety and improve types for PopoutPosition Co-Authored-By: fres621 <126067139+fres621@users.noreply.github.com> --- src/plugins/memberCount/MemberCount.tsx | 4 ++-- .../memberCount/OnlineMemberCountStore.ts | 8 ++++---- src/plugins/memberCount/index.tsx | 6 +++--- src/utils/discord.tsx | 6 +++--- src/webpack/common/types/components.d.ts | 18 ++++++++++-------- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/plugins/memberCount/MemberCount.tsx b/src/plugins/memberCount/MemberCount.tsx index 084e7ecc4..0a3f5e620 100644 --- a/src/plugins/memberCount/MemberCount.tsx +++ b/src/plugins/memberCount/MemberCount.tsx @@ -14,7 +14,7 @@ import { OnlineMemberCountStore } from "./OnlineMemberCountStore"; export function MemberCount({ isTooltip, tooltipGuildId }: { isTooltip?: true; tooltipGuildId?: string; }) { const currentChannel = useStateFromStores([SelectedChannelStore], () => getCurrentChannel()); - const guildId = isTooltip ? tooltipGuildId! : currentChannel.guild_id; + const guildId = isTooltip ? tooltipGuildId! : currentChannel?.guild_id; const totalCount = useStateFromStores( [GuildMemberCountStore], @@ -33,7 +33,7 @@ export function MemberCount({ isTooltip, tooltipGuildId }: { isTooltip?: true; t const threadGroups = useStateFromStores( [ThreadMemberListStore], - () => ThreadMemberListStore.getMemberListSections(currentChannel.id) + () => ThreadMemberListStore.getMemberListSections(currentChannel?.id) ); if (!isTooltip && (groups.length >= 1 || groups[0].id !== "unknown")) { diff --git a/src/plugins/memberCount/OnlineMemberCountStore.ts b/src/plugins/memberCount/OnlineMemberCountStore.ts index 8790f5e29..d74bea2a0 100644 --- a/src/plugins/memberCount/OnlineMemberCountStore.ts +++ b/src/plugins/memberCount/OnlineMemberCountStore.ts @@ -15,8 +15,8 @@ export const OnlineMemberCountStore = proxyLazy(() => { const onlineMemberMap = new Map(); class OnlineMemberCountStore extends Flux.Store { - getCount(guildId: string) { - return onlineMemberMap.get(guildId); + getCount(guildId?: string) { + return onlineMemberMap.get(guildId!); } async _ensureCount(guildId: string) { @@ -25,8 +25,8 @@ export const OnlineMemberCountStore = proxyLazy(() => { await PrivateChannelsStore.preload(guildId, GuildChannelStore.getDefaultChannel(guildId).id); } - ensureCount(guildId: string) { - if (onlineMemberMap.has(guildId)) return; + ensureCount(guildId?: string) { + if (!guildId || onlineMemberMap.has(guildId)) return; preloadQueue.push(() => this._ensureCount(guildId) diff --git a/src/plugins/memberCount/index.tsx b/src/plugins/memberCount/index.tsx index 7e591357d..85dcc4b2d 100644 --- a/src/plugins/memberCount/index.tsx +++ b/src/plugins/memberCount/index.tsx @@ -28,12 +28,12 @@ import { FluxStore } from "@webpack/types"; import { MemberCount } from "./MemberCount"; -export const GuildMemberCountStore = findStoreLazy("GuildMemberCountStore") as FluxStore & { getMemberCount(guildId: string): number | null; }; +export const GuildMemberCountStore = findStoreLazy("GuildMemberCountStore") as FluxStore & { getMemberCount(guildId?: string): number | null; }; export const ChannelMemberStore = findStoreLazy("ChannelMemberStore") as FluxStore & { - getProps(guildId: string, channelId: string): { groups: { count: number; id: string; }[]; }; + getProps(guildId?: string, channelId?: string): { groups: { count: number; id: string; }[]; }; }; export const ThreadMemberListStore = findStoreLazy("ThreadMemberListStore") as FluxStore & { - getMemberListSections(channelId: string): { [sectionId: string]: { sectionId: string; userIds: string[]; }; }; + getMemberListSections(channelId?: string): { [sectionId: string]: { sectionId: string; userIds: string[]; }; }; }; diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index c1d1e2253..4c7cc38a0 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -18,7 +18,7 @@ import { MessageObject } from "@api/MessageEvents"; import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; -import { Guild, Message, User } from "discord-types/general"; +import { Channel, Guild, Message, User } from "discord-types/general"; import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal"; @@ -54,12 +54,12 @@ export async function openInviteModal(code: string) { }); } -export function getCurrentChannel() { +export function getCurrentChannel(): Channel | undefined { return ChannelStore.getChannel(SelectedChannelStore.getChannelId()); } export function getCurrentGuild(): Guild | undefined { - return GuildStore.getGuild(getCurrentChannel()?.guild_id); + return GuildStore.getGuild(getCurrentChannel()?.guild_id!); } export function openPrivateChannel(userId: string) { diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index 0588d5e4c..6c7623339 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -91,7 +91,7 @@ export type Tooltip = ComponentType<{ /** Tooltip.Colors.BLACK */ color?: string; /** TooltipPositions.TOP */ - position?: string; + position?: PopoutPosition; tooltipClassName?: string; tooltipContentClassName?: string; @@ -110,7 +110,7 @@ export type TooltipContainer = ComponentType & { From 40512d729490091f61d645cc2e9eded9390ef26d Mon Sep 17 00:00:00 2001 From: Nyako <24845294+nyakowint@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:16:41 -0400 Subject: [PATCH 09/52] XSOverlay: fix profile images (#2788) Fixes https://github.com/Vendicated/Vencord/issues/2787 Co-authored-by: v --- src/plugins/xsOverlay/index.tsx | 40 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/plugins/xsOverlay/index.tsx b/src/plugins/xsOverlay/index.tsx index 12dbf6b61..4c5b7a80e 100644 --- a/src/plugins/xsOverlay/index.tsx +++ b/src/plugins/xsOverlay/index.tsx @@ -86,7 +86,7 @@ interface NotificationObject { title: string; content: string; useBase64Icon: boolean; - icon: ArrayBuffer | string; + icon: string; sourceApp: string; } @@ -320,23 +320,29 @@ function shouldIgnoreForChannelType(channel: Channel) { } function sendMsgNotif(titleString: string, content: string, message: Message) { - fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`).then(response => response.arrayBuffer()).then(result => { - const msgData: NotificationObject = { - type: 1, - timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout, - height: calculateHeight(content), - opacity: settings.store.opacity, - volume: settings.store.volume, - audioPath: settings.store.soundPath, - title: titleString, - content: content, - useBase64Icon: true, - icon: new TextDecoder().decode(result), - sourceApp: "Vencord" - }; + fetch(`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.png?size=128`) + .then(response => response.blob()) + .then(blob => new Promise(resolve => { + const r = new FileReader(); + r.onload = () => resolve((r.result as string).split(",")[1]); + r.readAsDataURL(blob); + })).then(result => { + const msgData: NotificationObject = { + type: 1, + timeout: settings.store.lengthBasedTimeout ? calculateTimeout(content) : settings.store.timeout, + height: calculateHeight(content), + opacity: settings.store.opacity, + volume: settings.store.volume, + audioPath: settings.store.soundPath, + title: titleString, + content: content, + useBase64Icon: true, + icon: result, + sourceApp: "Vencord" + }; - sendToOverlay(msgData); - }); + sendToOverlay(msgData); + }); } function sendOtherNotif(content: string, titleString: string) { From e6994e1946ea2b34c0b6b842d3a323beb9cfa3ef Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 5 Sep 2024 02:24:10 +0200 Subject: [PATCH 10/52] MentionAvatars: Fix compatibility with ServerInfo plugin --- src/plugins/mentionAvatars/styles.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/mentionAvatars/styles.css b/src/plugins/mentionAvatars/styles.css index 64eb41416..cf6e2c14c 100644 --- a/src/plugins/mentionAvatars/styles.css +++ b/src/plugins/mentionAvatars/styles.css @@ -9,3 +9,8 @@ .vc-mentionAvatars-role-icon { margin: 0 2px 0.2rem 4px; } + +/** don't display inside the ServerInfo modal owner mention */ +.vc-gp-owner .vc-mentionAvatars-icon { + display: none; +} From 61d3c08f1f6b9c44bd193aab4f8568734ba60ad8 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 5 Sep 2024 02:25:27 +0200 Subject: [PATCH 11/52] bump to v1.10.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 65a2f4512..e65e1b0a7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.9.9", + "version": "1.10.1", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 8890c8c6b4201121c559e671e0110b45937467c2 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 5 Sep 2024 02:33:07 +0200 Subject: [PATCH 12/52] fix Commands, Badges, RoleColorEverywhere --- src/api/Commands/index.ts | 7 ++++--- src/plugins/_api/badges/fixBadgeOverflow.css | 3 --- src/plugins/_api/badges/index.tsx | 4 +--- src/plugins/roleColorEverywhere/index.tsx | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 src/plugins/_api/badges/fixBadgeOverflow.css diff --git a/src/api/Commands/index.ts b/src/api/Commands/index.ts index 5e3fc8f4d..e5803ba02 100644 --- a/src/api/Commands/index.ts +++ b/src/api/Commands/index.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { Logger } from "@utils/Logger"; import { makeCodeblock } from "@utils/text"; import { sendBotMessage } from "./commandHelpers"; @@ -46,10 +47,10 @@ export let RequiredMessageOption: Option = ReqPlaceholder; export const _init = function (cmds: Command[]) { try { BUILT_IN = cmds; - OptionalMessageOption = cmds.find(c => c.name === "shrug")!.options![0]; - RequiredMessageOption = cmds.find(c => c.name === "me")!.options![0]; + OptionalMessageOption = cmds.find(c => (c.untranslatedName || c.displayName) === "shrug")!.options![0]; + RequiredMessageOption = cmds.find(c => (c.untranslatedName || c.displayName) === "me")!.options![0]; } catch (e) { - console.error("Failed to load CommandsApi"); + new Logger("CommandsAPI").error("Failed to load CommandsApi", e, " - cmds is", cmds); } return cmds; } as never; diff --git a/src/plugins/_api/badges/fixBadgeOverflow.css b/src/plugins/_api/badges/fixBadgeOverflow.css deleted file mode 100644 index 348d0ff38..000000000 --- a/src/plugins/_api/badges/fixBadgeOverflow.css +++ /dev/null @@ -1,3 +0,0 @@ -[class*="profileBadges"] { - flex: none; -} diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index cf00a0e29..c44d98b90 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -16,8 +16,6 @@ * along with this program. If not, see . */ -import "./fixBadgeOverflow.css"; - import { _getBadges, BadgePosition, BadgeUserArgs, ProfileBadge } from "@api/Badges"; import DonateButton from "@components/DonateButton"; import ErrorBoundary from "@components/ErrorBoundary"; @@ -79,7 +77,7 @@ export default definePlugin({ replace: "...$1.props,$& $1.image??" }, { - match: /(?<=text:(\i)\.description,.{0,50})children:/, + match: /(?<=text:(\i)\.description,.{0,200})children:/, replace: "children:$1.component ? $self.renderBadgeComponent({ ...$1 }) :" }, // conditionally override their onClick with badge.onClick if it exists diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx index 3e7d216b7..b5f66c098 100644 --- a/src/plugins/roleColorEverywhere/index.tsx +++ b/src/plugins/roleColorEverywhere/index.tsx @@ -57,7 +57,7 @@ export default definePlugin({ patches: [ // Chat Mentions { - find: 'location:"UserMention', + find: ".USER_MENTION)", replacement: [ { match: /onContextMenu:\i,color:\i,\.\.\.\i(?=,children:)(?<=user:(\i),channel:(\i).{0,500}?)/, From e5a4db646061de526f91c1849809bae28597c0b5 Mon Sep 17 00:00:00 2001 From: niko <57009359+hauntii@users.noreply.github.com> Date: Fri, 6 Sep 2024 07:40:29 -0400 Subject: [PATCH 13/52] TimeBarAllActivities: Fix not working (#2847) --- src/plugins/timeBarAllActivities/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/timeBarAllActivities/index.tsx b/src/plugins/timeBarAllActivities/index.tsx index 04f7ff9e7..91b1bc2f1 100644 --- a/src/plugins/timeBarAllActivities/index.tsx +++ b/src/plugins/timeBarAllActivities/index.tsx @@ -40,7 +40,7 @@ export default definePlugin({ settings, patches: [ { - find: ".Messages.USER_ACTIVITY_PLAYING", + find: ".gameState,children:", replacement: [ // Insert Spotify time bar component { From 9e7f8829f24f447c726dbf6002d16324df0e944d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:20:15 -0300 Subject: [PATCH 14/52] CustomRPC: Fix activity preview styling --- src/plugins/customRPC/index.tsx | 7 +++---- src/utils/constants.ts | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx index eebcd4ddb..f4b9ab060 100644 --- a/src/plugins/customRPC/index.tsx +++ b/src/plugins/customRPC/index.tsx @@ -26,12 +26,11 @@ import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { useAwaiter } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByCodeLazy, findComponentByCodeLazy } from "@webpack"; import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color"); const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile"); -const ActivityClassName = findByPropsLazy("activity", "buttonColor"); const ShowCurrentGame = getUserSettingLazy("status", "showCurrentGame")!; @@ -436,8 +435,8 @@ export default definePlugin({ -
- {activity[0] && + {activity[0] && } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index b0ad77fb1..6f98db607 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -39,7 +39,8 @@ export const Devs = /* #__PURE__*/ Object.freeze({ }, Arjix: { name: "ArjixWasTaken", - id: 674710789138939916n + id: 674710789138939916n, + badge: false }, Cyn: { name: "Cynosphere", From 868b2ea9f0134200d469bb7e8d037d709d9581a8 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:40:10 -0300 Subject: [PATCH 15/52] Fix SortFriendRequests received date --- src/plugins/index.ts | 4 ++-- src/plugins/sortFriendRequests/index.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/index.ts b/src/plugins/index.ts index e6caf7340..ac6821a63 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -66,14 +66,14 @@ export function addPatch(newPatch: Omit, pluginName: string) { patch.replacement = [patch.replacement]; } - patch.replacement = patch.replacement.filter(({ predicate }) => !predicate || predicate()); - if (IS_REPORTER) { patch.replacement.forEach(r => { delete r.predicate; }); } + patch.replacement = patch.replacement.filter(({ predicate }) => !predicate || predicate()); + patches.push(patch); } diff --git a/src/plugins/sortFriendRequests/index.tsx b/src/plugins/sortFriendRequests/index.tsx index 7033591bd..64eb13fe5 100644 --- a/src/plugins/sortFriendRequests/index.tsx +++ b/src/plugins/sortFriendRequests/index.tsx @@ -48,7 +48,7 @@ export default definePlugin({ find: ".Messages.FRIEND_REQUEST_CANCEL", replacement: { predicate: () => settings.store.showDates, - match: /subText:(\i)(?=,className:\i\.userInfo}\))(?<=user:(\i).+?)/, + match: /subText:(\i)(?<=user:(\i).+?)/, replace: (_, subtext, user) => `subText:$self.makeSubtext(${subtext},${user})` } }], @@ -66,7 +66,7 @@ export default definePlugin({ makeSubtext(text: string, user: User) { const since = this.getSince(user); return ( - + {text} {!isNaN(since.getTime()) && Received — {since.toDateString()}} From 56459bdcad39b8accacd05f715fab8a544555a6e Mon Sep 17 00:00:00 2001 From: Relitrix <46451374+relitrix@users.noreply.github.com> Date: Fri, 6 Sep 2024 18:33:23 +0300 Subject: [PATCH 16/52] new plugin AccountPanelServerProfile (#2836) --- .../accountPanelServerProfile/README.md | 7 + .../accountPanelServerProfile/index.tsx | 134 ++++++++++++++++++ src/utils/constants.ts | 4 + 3 files changed, 145 insertions(+) create mode 100644 src/plugins/accountPanelServerProfile/README.md create mode 100644 src/plugins/accountPanelServerProfile/index.tsx diff --git a/src/plugins/accountPanelServerProfile/README.md b/src/plugins/accountPanelServerProfile/README.md new file mode 100644 index 000000000..f837864b7 --- /dev/null +++ b/src/plugins/accountPanelServerProfile/README.md @@ -0,0 +1,7 @@ +# AccountPanelServerProfile + +Right click your account panel in the bottom left to view your profile in the current server + +![](https://github.com/user-attachments/assets/3228497d-488f-479c-93d2-a32ccdb08f0f) + +![](https://github.com/user-attachments/assets/6fc45363-d95f-4810-812f-2f9fb28b41b5) diff --git a/src/plugins/accountPanelServerProfile/index.tsx b/src/plugins/accountPanelServerProfile/index.tsx new file mode 100644 index 000000000..fe5df48ad --- /dev/null +++ b/src/plugins/accountPanelServerProfile/index.tsx @@ -0,0 +1,134 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; +import { Devs } from "@utils/constants"; +import { getCurrentChannel } from "@utils/discord"; +import definePlugin, { OptionType } from "@utils/types"; +import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { ContextMenuApi, Menu, useEffect, useRef } from "@webpack/common"; +import { User } from "discord-types/general"; + +interface UserProfileProps { + popoutProps: Record; + currentUser: User; + originalPopout: () => React.ReactNode; +} + +const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined"); +const styles = findByPropsLazy("accountProfilePopoutWrapper"); + +let openAlternatePopout = false; +let accountPanelRef: React.MutableRefObject | null> = { current: null }; + +const AccountPanelContextMenu = ErrorBoundary.wrap(() => { + const { prioritizeServerProfile } = settings.use(["prioritizeServerProfile"]); + + return ( + + { + openAlternatePopout = true; + accountPanelRef.current?.props.onMouseDown(); + accountPanelRef.current?.props.onClick(e); + }} + /> + settings.store.prioritizeServerProfile = !prioritizeServerProfile} + /> + + ); +}, { noop: true }); + +const settings = definePluginSettings({ + prioritizeServerProfile: { + type: OptionType.BOOLEAN, + description: "Prioritize Server Profile when left clicking your account panel", + default: false + } +}); + +export default definePlugin({ + name: "AccountPanelServerProfile", + description: "Right click your account panel in the bottom left to view your profile in the current server", + authors: [Devs.Nuckyz, Devs.relitrix], + settings, + + patches: [ + { + find: ".Messages.ACCOUNT_SPEAKING_WHILE_MUTED", + group: true, + replacement: [ + { + match: /(?<=\.SIZE_32\)}\);)/, + replace: "$self.useAccountPanelRef();" + }, + { + match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/, + replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalPopout:()=>{${originalPopout}}})` + }, + { + match: /\.AVATAR,children:.+?(?=renderPopout:)/, + replace: "$&onRequestClose:$self.onPopoutClose," + }, + { + match: /(?<=.avatarWrapper,)/, + replace: "ref:$self.accountPanelRef,onContextMenu:$self.openAccountPanelContextMenu," + } + ] + } + ], + + get accountPanelRef() { + return accountPanelRef; + }, + + useAccountPanelRef() { + useEffect(() => () => { + accountPanelRef.current = null; + }, []); + + return (accountPanelRef = useRef(null)); + }, + + openAccountPanelContextMenu(event: React.UIEvent) { + ContextMenuApi.openContextMenu(event, AccountPanelContextMenu); + }, + + onPopoutClose() { + openAlternatePopout = false; + }, + + UserProfile: ErrorBoundary.wrap(({ popoutProps, currentUser, originalPopout }: UserProfileProps) => { + if ( + (settings.store.prioritizeServerProfile && openAlternatePopout) || + (!settings.store.prioritizeServerProfile && !openAlternatePopout) + ) { + return originalPopout(); + } + + const currentChannel = getCurrentChannel(); + if (currentChannel?.getGuildId() == null) { + return originalPopout(); + } + + return ( +
+ +
+ ); + }, { noop: true }) +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 6f98db607..0572fa102 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -567,6 +567,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "niko", id: 341377368075796483n, }, + relitrix: { + name: "Relitrix", + id: 423165393901715456n, + }, RamziAH: { name: "RamziAH", id: 1279957227612147747n, From a765212cfea712f67dd82d025f8f9a56558cdbbe Mon Sep 17 00:00:00 2001 From: thororen <78185467+thororen1234@users.noreply.github.com> Date: Wed, 11 Sep 2024 06:50:55 -0400 Subject: [PATCH 17/52] NoTrack: Fix blocking analytics (#2857) --- src/plugins/_core/noTrack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts index de1c20562..8d6a1e76d 100644 --- a/src/plugins/_core/noTrack.ts +++ b/src/plugins/_core/noTrack.ts @@ -48,7 +48,7 @@ export default definePlugin({ }, }, { - find: ".METRICS,", + find: ".METRICS", replacement: [ { match: /this\._intervalId=/, From f27361f017330e8957b12b6eabcf4930ffcf7eb4 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:13:23 -0300 Subject: [PATCH 18/52] TimeBarAllActivities: Fix timestamp component --- src/plugins/ignoreActivities/index.tsx | 9 +------ src/plugins/noPendingCount/index.ts | 11 +-------- src/plugins/timeBarAllActivities/index.tsx | 28 ++++++++++++++-------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx index 02261b5ba..8c36e1d75 100644 --- a/src/plugins/ignoreActivities/index.tsx +++ b/src/plugins/ignoreActivities/index.tsx @@ -266,7 +266,7 @@ export default definePlugin({ replace: (m, props, nowPlaying) => `${m}$self.renderToggleGameActivityButton(${props},${nowPlaying}),` } }, - // Discord has 3 different components for activities. Currently, the last is the one being used + // Discord has 2 different components for activities. Currently, the last is the one being used { find: ".activityTitleText,variant", replacement: { @@ -274,13 +274,6 @@ export default definePlugin({ replace: (m, props) => `${m}$self.renderToggleActivityButton(${props}),` }, }, - { - find: ".activityCardDetails,children", - replacement: { - match: /\.activityCardDetails.+?children:(\i\.application)\.name.*?}\),/, - replace: (m, props) => `${m}$self.renderToggleActivityButton(${props}),` - } - }, { find: ".promotedLabelWrapperNonBanner,children", replacement: { diff --git a/src/plugins/noPendingCount/index.ts b/src/plugins/noPendingCount/index.ts index 0995621fa..d3e27563b 100644 --- a/src/plugins/noPendingCount/index.ts +++ b/src/plugins/noPendingCount/index.ts @@ -62,16 +62,7 @@ export default definePlugin({ replace: "return 0;" } }, - // New message requests hook - { - find: 'location:"use-message-requests-count"', - predicate: () => settings.store.hideMessageRequestsCount, - replacement: { - match: /getNonChannelAckId\(\i\.\i\.MESSAGE_REQUESTS\).+?return /, - replace: "$&0;" - } - }, - // Old message requests hook + // Message requests hook { find: "getMessageRequestsCount(){", predicate: () => settings.store.hideMessageRequestsCount, diff --git a/src/plugins/timeBarAllActivities/index.tsx b/src/plugins/timeBarAllActivities/index.tsx index 91b1bc2f1..660d20bbf 100644 --- a/src/plugins/timeBarAllActivities/index.tsx +++ b/src/plugins/timeBarAllActivities/index.tsx @@ -5,9 +5,11 @@ */ import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findComponentByCodeLazy } from "@webpack"; +import { RequiredDeep } from "type-fest"; interface Activity { timestamps?: ActivityTimestamps; @@ -18,7 +20,15 @@ interface ActivityTimestamps { end?: string; } -const ActivityTimeBar = findComponentByCodeLazy(".Millis.HALF_SECOND", ".bar", ".progress"); +interface TimebarComponentProps { + activity: Activity; +} + +const ActivityTimeBar = findComponentByCodeLazy(".bar", ".progress", "(100*"); + +function isActivityTimestamped(activity: Activity): activity is RequiredDeep { + return activity.timestamps != null && activity.timestamps.start != null && activity.timestamps.end != null; +} export const settings = definePluginSettings({ hideActivityDetailText: { @@ -45,7 +55,7 @@ export default definePlugin({ // Insert Spotify time bar component { match: /\(0,.{0,30}activity:(\i),className:\i\.badges\}\)/g, - replace: "$&,$self.getTimeBar($1)" + replace: "$&,$self.TimebarComponent({activity:$1})" }, // Hide the large title on listening activities, to make them look more like Spotify (also visible from hovering over the large icon) { @@ -64,13 +74,11 @@ export default definePlugin({ } ], - isActivityTimestamped(activity: Activity) { - return activity.timestamps != null && activity.timestamps.start != null && activity.timestamps.end != null; - }, + isActivityTimestamped, - getTimeBar(activity: Activity) { - if (this.isActivityTimestamped(activity)) { - return ; - } - } + TimebarComponent: ErrorBoundary.wrap(({ activity }: TimebarComponentProps) => { + if (!isActivityTimestamped(activity)) return null; + + return ; + }, { noop: true }) }); From b82254235204a3f0e784c623d499b2e3274a83d5 Mon Sep 17 00:00:00 2001 From: sadan4 <117494111+sadan4@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:23:43 -0400 Subject: [PATCH 19/52] BetterFolders: Fix pending clan applications (#2867) --- src/plugins/betterFolders/README.md | 11 ++++++++ src/plugins/betterFolders/index.tsx | 39 +++++++++++++++++++---------- 2 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 src/plugins/betterFolders/README.md diff --git a/src/plugins/betterFolders/README.md b/src/plugins/betterFolders/README.md new file mode 100644 index 000000000..658c6f1db --- /dev/null +++ b/src/plugins/betterFolders/README.md @@ -0,0 +1,11 @@ +# Better Folders + +Better Folders offers a variety of options to improve your folder experience + +Always show the folder icon, regardless of if the folder is open or not + +Only have one folder open at a time + +Open folders in a sidebar: + +![A folder open in a separate sidebar](https://github.com/user-attachments/assets/432d3146-8091-4bae-9c1e-c19046c72947) diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 0bef0933d..c2969988b 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -30,9 +30,9 @@ enum FolderIconDisplay { MoreThanOneFolderExpanded } -const GuildsTree = findLazy(m => m.prototype?.moveNextTo); -const SortedGuildStore = findStoreLazy("SortedGuildStore"); export const ExpandedGuildFolderStore = findStoreLazy("ExpandedGuildFolderStore"); +const SortedGuildStore = findStoreLazy("SortedGuildStore"); +const GuildsTree = findLazy(m => m.prototype?.moveNextTo); const FolderUtils = findByPropsLazy("move", "toggleGuildFolderExpand"); let lastGuildId = null as string | null; @@ -118,17 +118,17 @@ export default definePlugin({ // If we are rendering the Better Folders sidebar, we filter out guilds that are not in folders and unexpanded folders { match: /\[(\i)\]=(\(0,\i\.\i\).{0,40}getGuildsTree\(\).+?}\))(?=,)/, - replace: (_, originalTreeVar, rest) => `[betterFoldersOriginalTree]=${rest},${originalTreeVar}=$self.getGuildTree(!!arguments[0].isBetterFolders,betterFoldersOriginalTree,arguments[0].betterFoldersExpandedIds)` + replace: (_, originalTreeVar, rest) => `[betterFoldersOriginalTree]=${rest},${originalTreeVar}=$self.getGuildTree(!!arguments[0]?.isBetterFolders,betterFoldersOriginalTree,arguments[0]?.betterFoldersExpandedIds)` }, // If we are rendering the Better Folders sidebar, we filter out everything but the servers and folders from the GuildsBar Guild List children { match: /lastTargetNode:\i\[\i\.length-1\].+?Fragment.+?\]}\)\]/, - replace: "$&.filter($self.makeGuildsBarGuildListFilter(!!arguments[0].isBetterFolders))" + replace: "$&.filter($self.makeGuildsBarGuildListFilter(!!arguments[0]?.isBetterFolders))" }, // If we are rendering the Better Folders sidebar, we filter out everything but the scroller for the guild list from the GuildsBar Tree children { match: /unreadMentionsIndicatorBottom,.+?}\)\]/, - replace: "$&.filter($self.makeGuildsBarTreeFilter(!!arguments[0].isBetterFolders))" + replace: "$&.filter($self.makeGuildsBarTreeFilter(!!arguments[0]?.isBetterFolders))" }, // Export the isBetterFolders variable to the folders component { @@ -167,31 +167,31 @@ export default definePlugin({ { predicate: () => settings.store.keepIcons, match: /(?<=let{folderNode:\i,setNodeRef:\i,.+?expanded:(\i),.+?;)(?=let)/, - replace: (_, isExpanded) => `${isExpanded}=!!arguments[0].isBetterFolders&&${isExpanded};` + replace: (_, isExpanded) => `${isExpanded}=!!arguments[0]?.isBetterFolders&&${isExpanded};` }, // Disable expanding and collapsing folders transition in the normal GuildsBar sidebar { predicate: () => !settings.store.keepIcons, match: /(?<=\.Messages\.SERVER_FOLDER_PLACEHOLDER.+?useTransition\)\()/, - replace: "!!arguments[0].isBetterFolders&&" + replace: "$self.shouldShowTransition(arguments[0])&&" }, // If we are rendering the normal GuildsBar sidebar, we avoid rendering guilds from folders that are expanded { predicate: () => !settings.store.keepIcons, match: /expandedFolderBackground,.+?,(?=\i\(\(\i,\i,\i\)=>{let{key.{0,45}ul)(?<=selected:\i,expanded:(\i),.+?)/, - replace: (m, isExpanded) => `${m}!arguments[0].isBetterFolders&&${isExpanded}?null:` + replace: (m, isExpanded) => `${m}$self.shouldRenderContents(arguments[0],${isExpanded})?null:` }, { // Decide if we should render the expanded folder background if we are rendering the Better Folders sidebar predicate: () => settings.store.showFolderIcon !== FolderIconDisplay.Always, match: /(?<=\.wrapper,children:\[)/, - replace: "$self.shouldShowFolderIconAndBackground(!!arguments[0].isBetterFolders,arguments[0].betterFoldersExpandedIds)&&" + replace: "$self.shouldShowFolderIconAndBackground(!!arguments[0]?.isBetterFolders,arguments[0]?.betterFoldersExpandedIds)&&" }, { // Decide if we should render the expanded folder icon if we are rendering the Better Folders sidebar predicate: () => settings.store.showFolderIcon !== FolderIconDisplay.Always, match: /(?<=\.expandedFolderBackground.+?}\),)(?=\i,)/, - replace: "!$self.shouldShowFolderIconAndBackground(!!arguments[0].isBetterFolders,arguments[0].betterFoldersExpandedIds)?null:" + replace: "!$self.shouldShowFolderIconAndBackground(!!arguments[0]?.isBetterFolders,arguments[0]?.betterFoldersExpandedIds)?null:" } ] }, @@ -201,7 +201,7 @@ export default definePlugin({ replacement: { // Render the Better Folders sidebar match: /(?<=({className:\i\.guilds,themeOverride:\i})\))/, - replace: ",$self.FolderSideBar($1)" + replace: ",$self.FolderSideBar({...$1})" } }, { @@ -306,7 +306,20 @@ export default definePlugin({ } }, - FolderSideBar: guildsBarProps => , + shouldShowTransition(props: any) { + // Pending guilds + if (props?.folderNode?.id === 1) return true; - closeFolders + return !!props?.isBetterFolders; + }, + + shouldRenderContents(props: any, isExpanded: boolean) { + // Pending guilds + if (props?.folderNode?.id === 1) return false; + + return !props?.isBetterFolders && isExpanded; + }, + + FolderSideBar, + closeFolders, }); From 292f7d71d3bf1ce8115bd6b7b73597ade12d0645 Mon Sep 17 00:00:00 2001 From: Ryan Cao <70191398+ryanccn@users.noreply.github.com> Date: Sat, 14 Sep 2024 22:59:05 +0800 Subject: [PATCH 20/52] AppleMusicRichPresence: fix metadata fetching (#2864) --- src/plugins/appleMusic.desktop/index.tsx | 2 +- src/plugins/appleMusic.desktop/native.ts | 80 +++++++++++++----------- 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/plugins/appleMusic.desktop/index.tsx b/src/plugins/appleMusic.desktop/index.tsx index 6fa989cdd..327fafc30 100644 --- a/src/plugins/appleMusic.desktop/index.tsx +++ b/src/plugins/appleMusic.desktop/index.tsx @@ -120,7 +120,7 @@ const settings = definePluginSettings({ stateString: { type: OptionType.STRING, description: "Activity state format string", - default: "{artist}" + default: "{artist} · {album}" }, largeImageType: { type: OptionType.SELECT, diff --git a/src/plugins/appleMusic.desktop/native.ts b/src/plugins/appleMusic.desktop/native.ts index 2eb2a0757..7d69a85ae 100644 --- a/src/plugins/appleMusic.desktop/native.ts +++ b/src/plugins/appleMusic.desktop/native.ts @@ -11,37 +11,11 @@ import type { TrackData } from "."; const exec = promisify(execFile); -// function exec(file: string, args: string[] = []) { -// return new Promise<{ code: number | null, stdout: string | null, stderr: string | null; }>((resolve, reject) => { -// const process = spawn(file, args, { stdio: [null, "pipe", "pipe"] }); - -// let stdout: string | null = null; -// process.stdout.on("data", (chunk: string) => { stdout ??= ""; stdout += chunk; }); -// let stderr: string | null = null; -// process.stderr.on("data", (chunk: string) => { stdout ??= ""; stderr += chunk; }); - -// process.on("exit", code => { resolve({ code, stdout, stderr }); }); -// process.on("error", err => reject(err)); -// }); -// } - async function applescript(cmds: string[]) { const { stdout } = await exec("osascript", cmds.map(c => ["-e", c]).flat()); return stdout; } -function makeSearchUrl(type: string, query: string) { - const url = new URL("https://tools.applemediaservices.com/api/apple-media/music/US/search.json"); - url.searchParams.set("types", type); - url.searchParams.set("limit", "1"); - url.searchParams.set("term", query); - return url; -} - -const requestOptions: RequestInit = { - headers: { "user-agent": "Mozilla/5.0 (Windows NT 10.0; rv:125.0) Gecko/20100101 Firefox/125.0" }, -}; - interface RemoteData { appleMusicLink?: string, songLink?: string, @@ -51,6 +25,24 @@ interface RemoteData { let cachedRemoteData: { id: string, data: RemoteData; } | { id: string, failures: number; } | null = null; +const APPLE_MUSIC_BUNDLE_REGEX = /