diff --git a/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx b/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx index 8c97f625e..7e3b2ee8d 100644 --- a/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx +++ b/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx @@ -5,7 +5,7 @@ */ import { classNameFactory } from "@api/Styles"; -import { getIntlMessage } from "@utils/discord"; +import { getGuildAcronym, getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import { closeModal, openModal } from "@utils/modal"; import { findComponentByCodeLazy } from "@webpack"; @@ -47,7 +47,7 @@ function BookmarkIcon({ bookmark }: { bookmark: Bookmark | BookmarkFolder; }) { className={cl("bookmark-icon")} /> :
- {guild.acronym} + {getGuildAcronym(guild)}
; if (channel?.recipients?.length) { diff --git a/src/equicordplugins/channelTabs/components/ChannelTab.tsx b/src/equicordplugins/channelTabs/components/ChannelTab.tsx index f8350ef4f..2ce99b87e 100644 --- a/src/equicordplugins/channelTabs/components/ChannelTab.tsx +++ b/src/equicordplugins/channelTabs/components/ChannelTab.tsx @@ -5,7 +5,7 @@ */ import { classNameFactory } from "@api/Styles"; -import { getIntlMessage, getUniqueUsername } from "@utils/discord"; +import { getGuildAcronym, getIntlMessage, getUniqueUsername } from "@utils/discord"; import { classes } from "@utils/misc"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { Avatar, ChannelStore, ContextMenuApi, GuildStore, PresenceStore, ReadStateStore, Text, TypingStore, useDrag, useDrop, useRef, UserStore, useStateFromStores } from "@webpack/common"; @@ -37,7 +37,7 @@ const GuildIcon = ({ guild }: { guild: Guild; }) => { className={cl("icon")} /> :
- {guild.acronym} + {getGuildAcronym(guild)}
; }; diff --git a/src/equicordplugins/fastDeleteChannels/index.tsx b/src/equicordplugins/fastDeleteChannels/index.tsx index 01e2d5e5e..3d986edce 100644 --- a/src/equicordplugins/fastDeleteChannels/index.tsx +++ b/src/equicordplugins/fastDeleteChannels/index.tsx @@ -4,17 +4,34 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { definePluginSettings } from "@api/Settings"; import { EquicordDevs } from "@utils/constants"; -import definePlugin from "@utils/types"; +import definePlugin, { OptionType } from "@utils/types"; import { Constants, PermissionsBits, PermissionStore, React, RestAPI, useCallback, useEffect, useState } from "@webpack/common"; -const showIcon = () => { - const [show, setShow] = useState(false); +const validKeycodes = [ + "Backspace", "Tab", "Enter", "ShiftLeft", "ShiftRight", "ControlLeft", "ControlRight", "AltLeft", "AltRight", "Pause", "CapsLock", + "Escape", "Space", "PageUp", "PageDown", "End", "Home", "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown", "PrintScreen", "Insert", + "Delete", "Digit0", "Digit1", "Digit2", "Digit3", "Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9", "KeyA", "KeyB", "KeyC", + "KeyD", "KeyE", "KeyF", "KeyG", "KeyH", "KeyI", "KeyJ", "KeyK", "KeyL", "KeyM", "KeyN", "KeyO", "KeyP", "KeyQ", "KeyR", "KeyS", "KeyT", + "KeyU", "KeyV", "KeyW", "KeyX", "KeyY", "KeyZ", "MetaLeft", "MetaRight", "ContextMenu", "Numpad0", "Numpad1", "Numpad2", "Numpad3", + "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9", "NumpadMultiply", "NumpadAdd", "NumpadSubtract", "NumpadDecimal", + "NumpadDivide", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "NumLock", "ScrollLock", +]; - const handleKeys = useCallback(e => { - const keysHeld = e.ctrlKey && e.altKey; - setShow(keysHeld); - }, []); +function showIcon() { + const [show, setShow] = useState(false); + const { keyBind, reqCtrl, reqShift, reqAlt } = settings.store; + + const handleKeys = useCallback((e: KeyboardEvent) => { + const isMatchingKey = + e.code === keyBind && + (!reqCtrl || e.ctrlKey) && + (!reqShift || e.shiftKey) && + (!reqAlt || e.altKey); + + setShow(isMatchingKey); + }, [keyBind, reqCtrl, reqShift, reqAlt]); useEffect(() => { window.addEventListener("keydown", handleKeys); @@ -27,12 +44,38 @@ const showIcon = () => { }, [handleKeys]); return show; -}; +} + +// TY ToggleVideoBind +const settings = definePluginSettings({ + keyBind: { + description: "The key to toggle trash when pressed.", + type: OptionType.STRING, + default: "KeyZ", + isValid: (value: string) => validKeycodes.includes(value), + }, + reqCtrl: { + description: "Require control to be held.", + type: OptionType.BOOLEAN, + default: true, + }, + reqShift: { + description: "Require shift to be held.", + type: OptionType.BOOLEAN, + default: true, + }, + reqAlt: { + description: "Require alt to be held.", + type: OptionType.BOOLEAN, + default: false, + }, +}); export default definePlugin({ name: "FastDeleteChannels", - description: "Adds a trash icon to delete channels when holding ctrl + alt", + description: "Adds a trash icon to delete channels", authors: [EquicordDevs.thororen], + settings, patches: [ // TY TypingIndicator { diff --git a/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx b/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx index 2673e1d40..cd67e6f3a 100644 --- a/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx +++ b/src/equicordplugins/hideServers/components/HiddenServersMenu.tsx @@ -5,6 +5,7 @@ */ import { classNameFactory } from "@api/Styles"; +import { getGuildAcronym } from "@utils/discord"; import { classes } from "@utils/misc"; import { closeModal, @@ -25,14 +26,8 @@ import { HiddenServersStore } from "../HiddenServersStore"; const cl = classNameFactory("vc-hideservers-"); const IconClasses = findByPropsLazy("icon", "acronym", "childWrapper"); -function HiddenServersModal({ - modalProps, - close, -}: { - modalProps: ModalProps; - close(): void; -}) { - const servers = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuildsDetail()); +function HiddenServersModal({ modalProps, close }: { modalProps: ModalProps; close(): void; }) { + const guilds = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuildsDetail()); return ( @@ -43,23 +38,26 @@ function HiddenServersModal({ - + ); } -export function HiddenServersMenu({ servers }: { servers: Guild[]; }) { +export function HiddenServersMenu({ guilds }: { guilds: Guild[]; }) { return
- {servers.length > 0 ? ( - servers.map(server => ( -
+ {guilds.length > 0 ? ( + guilds.map(guild => ( +
- {server.icon - ? @@ -69,17 +67,17 @@ export function HiddenServersMenu({ servers }: { servers: Guild[]; }) { IconClasses.childWrapper, IconClasses.acronym )}> - {server.acronym} + {getGuildAcronym(guild)}
}
- {server.name} + {guild.name} diff --git a/src/equicordplugins/hideServers/settings.tsx b/src/equicordplugins/hideServers/settings.tsx index 1f6848247..3ea989b7b 100644 --- a/src/equicordplugins/hideServers/settings.tsx +++ b/src/equicordplugins/hideServers/settings.tsx @@ -30,7 +30,7 @@ export default definePluginSettings({ description: "Remove hidden servers", component: () => { const detail = useStateFromStores([HiddenServersStore], () => HiddenServersStore.hiddenGuildsDetail()); - return ; + return ; } }, resetHidden: { diff --git a/src/equicordplugins/noDeleteSafety/index.tsx b/src/equicordplugins/noDeleteSafety/index.tsx index c2fc75058..d9d6247b6 100644 --- a/src/equicordplugins/noDeleteSafety/index.tsx +++ b/src/equicordplugins/noDeleteSafety/index.tsx @@ -43,7 +43,7 @@ export default definePlugin({ { find: ".DELETE,onClick(){let", replacement: { - match: /let \i=(\i).guild.toString\(\)/, + match: /let\{name:\i\}=\i\.guild/, replace: "$self.HandleGuildDeleteModal($1);$&" } } diff --git a/src/equicordplugins/soundBoardLogger/utils.ts b/src/equicordplugins/soundBoardLogger/utils.ts index 7c192bcb1..12f547cf6 100644 --- a/src/equicordplugins/soundBoardLogger/utils.ts +++ b/src/equicordplugins/soundBoardLogger/utils.ts @@ -47,13 +47,13 @@ export const playSound = id => { export async function downloadAudio(id: string): Promise { const filename = id + settings.store.FileType; - const data = await fetch(`https://cdn.discordapp.com/soundboard-sounds/${id}`).then(e => e.arrayBuffer()); - + const original = await fetch(`https://cdn.discordapp.com/soundboard-sounds/${id}`).then(res => res.arrayBuffer()); if (IS_DISCORD_DESKTOP) { + const data = new Uint8Array(original); DiscordNative.fileManager.saveWithDialog(data, filename); } else { - saveFile(new File([data], filename, { type: "audio/ogg" })); + saveFile(new File([original], filename, { type: "audio/ogg" })); } } diff --git a/src/equicordplugins/toggleVideoBind/index.ts b/src/equicordplugins/toggleVideoBind/index.ts index e4b49b280..65b9df159 100644 --- a/src/equicordplugins/toggleVideoBind/index.ts +++ b/src/equicordplugins/toggleVideoBind/index.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { definePluginSettings } from "@api/Settings"; +import { definePluginSettings, migratePluginSettings } from "@api/Settings"; import { EquicordDevs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; @@ -56,8 +56,9 @@ function handleKeydown({ code, ctrlKey, shiftKey, altKey }: KeyboardEvent) { }); } +migratePluginSettings("ToggleVideoBind", "toggleVideoBind"); export default definePlugin({ - name: "toggleVideoBind", + name: "ToggleVideoBind", description: "Adds a customizable bind to toggle webcam.", authors: [EquicordDevs.mochienya], settings, diff --git a/src/equicordplugins/vencordRPC/index.ts b/src/equicordplugins/vencordRPC/index.ts index ed6ec655b..4a4a5126e 100644 --- a/src/equicordplugins/vencordRPC/index.ts +++ b/src/equicordplugins/vencordRPC/index.ts @@ -9,7 +9,7 @@ import { Devs } from "@utils/constants"; import { isTruthy } from "@utils/guards"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { ApplicationAssetUtils, ChannelStore, FluxDispatcher, GuildStore, PresenceStore, RelationshipStore, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; +import { ApplicationAssetUtils, ChannelStore, FluxDispatcher, GuildStore, IconUtils, PresenceStore, RelationshipStore, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; import { FluxStore } from "@webpack/types"; import { Channel } from "discord-types/general"; @@ -169,6 +169,12 @@ const settings = definePluginSettings({ if (value && value < 0) return "End timestamp must be greater than 0."; return true; } + }, + secretStuff: { + type: OptionType.STRING, + description: "A list of server/channel ids separated by commas, which are hidden from the RPC.", + onChange: onChange, + default: "" } }); @@ -227,6 +233,10 @@ function getChannelIconURL(channel: Channel): string { return chino; } +function getSecretStuff(): string[] { + return settings.store.secretStuff.split(",").map(id => id.trim()).filter(Boolean); +} + async function createActivity(): Promise { const { @@ -260,7 +270,15 @@ async function createActivity(): Promise { const currentUser = UserStore.getCurrentUser(); if (userAvatarAsSmallImage) imageSmall = currentUser.getAvatarURL(undefined, undefined, true) || chino; - if (!channelId) { + const secretStuff = getSecretStuff(); + const isSecret = secretStuff.includes(channelId) || secretStuff.includes(guildId); + + if (isSecret) { + appName = "Hidden Channel/Guild"; + details = "#secret"; + state = "hehe"; + imageBig = chino; + } else if (!channelId) { appName = "Friends List"; details = `${onlineFriendCount()} online / ${totalFriendCount()} total`; state = `${GuildStore.getGuildCount()} servers`; @@ -272,7 +290,7 @@ async function createActivity(): Promise { if (guild) { details = guild.name; state = memberCount(); - imageBig = guild.getIconURL(128, true) || chino; + imageBig = IconUtils.getGuildIconURL({ id: guild.id, icon: guild.icon, canAnimate: true, size: 512 }) || chino; if (guild.vanityURLCode) { buttonOneText = `Join ${guild.name.slice(0, 26)}`; buttonOneURL = `https://discord.gg/${guild.vanityURLCode}`; @@ -301,7 +319,7 @@ async function createActivity(): Promise { appName = `#${channel.name}`; details = guild.name; state = memberCount(); - imageBig = guild.getIconURL(128, true) || chino; + imageBig = IconUtils.getGuildIconURL({ id: guild.id, icon: guild.icon, canAnimate: true, size: 512 }) || chino; if (guild.vanityURLCode) { buttonOneText = `Join ${guild.name.slice(0, 31 - 5)}`; buttonOneURL = `https://discord.gg/${guild.vanityURLCode}`; diff --git a/src/plugins/expressionCloner/index.tsx b/src/plugins/expressionCloner/index.tsx index a835440a8..5c555169f 100644 --- a/src/plugins/expressionCloner/index.tsx +++ b/src/plugins/expressionCloner/index.tsx @@ -20,12 +20,13 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co import { migratePluginSettings } from "@api/Settings"; import { CheckedTextInput } from "@components/CheckedTextInput"; import { Devs } from "@utils/constants"; +import { getGuildAcronym } from "@utils/discord"; import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal"; import definePlugin from "@utils/types"; import { findByCodeLazy } from "@webpack"; -import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, StickerStore, Toasts, Tooltip, UserStore } from "@webpack/common"; +import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, IconUtils, Menu, PermissionsBits, PermissionStore, React, RestAPI, StickerStore, Toasts, Tooltip, UserStore } from "@webpack/common"; import { Guild } from "discord-types/general"; import { Promisable } from "type-fest"; @@ -249,13 +250,18 @@ function CloneModal({ data }: { data: Sticker | Emoji; }) { width: "100%", height: "100%", }} - src={g.getIconURL(512, true)} + src={IconUtils.getGuildIconURL({ + id: g.id, + icon: g.icon, + canAnimate: true, + size: 512 + })} alt={g.name} /> ) : ( - {g.acronym} + {getGuildAcronym(g)} )}
diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 432d1c1cd..577d8bd7f 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -18,7 +18,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; -import { getIntlMessage } from "@utils/discord"; +import { getIntlMessage, hasGuildFeature } from "@utils/discord"; import definePlugin from "@utils/types"; import { Constants, GuildStore, PermissionStore, RestAPI } from "@webpack/common"; @@ -27,8 +27,8 @@ function showDisableInvites(guildId: string) { if (!guild) return false; return ( - // @ts-ignore - !guild.hasFeature("INVITES_DISABLED") && + // @ts-expect-error + !hasGuildFeature(guild, "INVITES_DISABLED") && PermissionStore.getGuildPermissionProps(guild).canManageRoles ); } diff --git a/src/plugins/seeSummaries/index.tsx b/src/plugins/seeSummaries/index.tsx index de50e0a9d..343348f1e 100644 --- a/src/plugins/seeSummaries/index.tsx +++ b/src/plugins/seeSummaries/index.tsx @@ -7,6 +7,7 @@ import { DataStore } from "@api/index"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; +import { hasGuildFeature } from "@utils/discord"; import definePlugin, { OptionType } from "@utils/types"; import { findByCodeLazy, findByPropsLazy } from "@webpack"; import { ChannelStore, GuildStore } from "@webpack/common"; @@ -57,7 +58,7 @@ export default definePlugin({ { find: "SUMMARIZEABLE.has", replacement: { - match: /\i\.hasFeature\(\i\.\i\.SUMMARIES_ENABLED\w+?\)/g, + match: /\i\.features\.has\(\i\.\i\.SUMMARIES_ENABLED\w+?\)/g, replace: "true" } }, @@ -109,7 +110,8 @@ export default definePlugin({ const channel = ChannelStore.getChannel(channelId); // SUMMARIES_ENABLED feature is not in discord-types const guild = GuildStore.getGuild(channel.guild_id); - // @ts-ignore - return guild.hasFeature("SUMMARIES_ENABLED_GA"); + + // @ts-expect-error + return hasGuildFeature(guild, "SUMMARIES_ENABLED_GA"); } }); diff --git a/src/plugins/serverInfo/GuildInfoModal.tsx b/src/plugins/serverInfo/GuildInfoModal.tsx index d22404f78..e554a5aad 100644 --- a/src/plugins/serverInfo/GuildInfoModal.tsx +++ b/src/plugins/serverInfo/GuildInfoModal.tsx @@ -7,7 +7,7 @@ import "./styles.css"; import { classNameFactory } from "@api/Styles"; -import { openImageModal, openUserProfile } from "@utils/discord"; +import { getGuildAcronym, openImageModal, openUserProfile } from "@utils/discord"; import { classes } from "@utils/misc"; import { ModalRoot, ModalSize, openModal } from "@utils/modal"; import { useAwaiter } from "@utils/react"; @@ -107,7 +107,7 @@ function GuildInfoModal({ guild }: GuildProps) { width: 512, })} /> - :
{guild.acronym}
+ :
{getGuildAcronym(guild)}
}
@@ -374,7 +374,7 @@ function MutualServerIcons({ member }: { member: MemberWithMutuals; }) { {iconUrl ? ( ) : ( -
{guild.acronym}
+
{getGuildAcronym(guild)}
)}
))} diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index 0fb225ddd..b49750a1d 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -48,6 +48,11 @@ const settings = definePluginSettings({ default: false, description: "Use friend names in place of usernames (overrides Display Names option if applicable)" }, + showGradient: { + type: OptionType.BOOLEAN, + default: false, + description: "Whether to show gradient for suffix", + }, memberList: { type: OptionType.BOOLEAN, default: false, @@ -66,10 +71,11 @@ const settings = definePluginSettings({ description: "Show usernames in emoji reactions", restartNeeded: true }, - showGradient: { + userProfilePopout: { type: OptionType.BOOLEAN, default: false, - description: "Whether to show gradient for suffix", + description: "Show usernames in user profile popout", + restartNeeded: true }, }); @@ -95,6 +101,16 @@ export default definePlugin({ replace: "$self.renderUsername(arguments[0])" } }, + { + find: "#{intl::REACTION_TOOLTIP_1}", + predicate: () => settings.store.emojiReactions, + replacement: [ + { + match: /\i\.\i\.getName\((\i),null==.{0,15},(\i)\)/, + replace: "$self.getUsername($2,$1)" + }, + ] + }, { find: "._areActivitiesExperimentallyHidden=(", predicate: () => settings.store.memberList, @@ -108,21 +124,27 @@ export default definePlugin({ predicate: () => settings.store.voiceChannelList, replacement: [ { - match: /(?<=children:\[)null!=\i\?\i:\i\.\i\.getName\((\i)\)(?=.*?contextGuildId:(\i))/, + match: /null!=\i\?\i:\i\.\i\.getName\((\i)\)(?=.*?contextGuildId:(\i))/, replace: "$self.getUsername($1,$2)" }, ] }, { - find: "#{intl::REACTION_TOOLTIP_1}", - predicate: () => settings.store.emojiReactions, - replacement: [ - { - match: /\i\.\i\.getName\((\i),null==.{0,15},(\i)\)/g, - replace: "$self.getUsername($2,$1)" - }, - ] + find: ".hasAvatarForGuild(null==", + predicate: () => settings.store.userProfilePopout, + replacement: { + match: /(?<=user:(\i).{0,15}\}\),nickname:)\i(?=.*?guildId:(null==\i\?void 0:\i\.id))/, + replace: "$self.getUsername($1,$2)" + } }, + { + find: "friendRequestBanner})", + predicate: () => settings.store.userProfilePopout, + replacement: { + match: /(?<=user:(\i).{0,15}guildId:(\i).*?nickname:)\i/, + replace: "$self.getUsername($1,$2)" + } + } ], settings, getUsername, diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index e04ad201c..fce909c3e 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -19,6 +19,7 @@ import { MessageObject } from "@api/MessageEvents"; import { ChannelActionCreators, ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, i18n, IconUtils, InviteActions, MessageActions, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Channel, Guild, Message, User } from "discord-types/general"; +import GuildFeatures from "discord-types/other/Constants"; import { Except } from "type-fest"; import { runtimeHashMessageKey } from "./intlHash"; @@ -218,3 +219,15 @@ export function getEmojiURL(id: string, animated: boolean, size: number) { const url = IconUtils.getEmojiURL({ id, animated, size }); return animated ? url.replace(".webp", ".gif") : url; } + +// Discord has a similar function in their code +export function getGuildAcronym(guild: Guild): string { + return guild.name + .replaceAll("'s ", " ") + .replace(/\w+/g, m => m[0]) + .replace(/\s/g, ""); +} + +export function hasGuildFeature(guild: Guild, feature: keyof GuildFeatures["GuildFeatures"]): boolean { + return guild.features?.has(feature) ?? false; +}