diff --git a/package.json b/package.json index bff89bba..32c634cc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "equicord", "private": "true", - "version": "1.10.4", + "version": "1.10.5", "description": "The other cutest Discord client mod", "homepage": "https://github.com/Equicord/Equicord#readme", "bugs": { @@ -119,4 +119,4 @@ "node": ">=18", "pnpm": ">=9" } -} \ No newline at end of file +} diff --git a/src/plugins/_api/dynamicImageModalApi.ts b/src/plugins/_api/dynamicImageModalApi.ts new file mode 100644 index 00000000..2ce51400 --- /dev/null +++ b/src/plugins/_api/dynamicImageModalApi.ts @@ -0,0 +1,24 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; + + +export default definePlugin({ + name: "DynamicImageModalAPI", + authors: [Devs.sadan, Devs.Nuckyz], + description: "Allows you to omit either width or height when opening an image modal", + patches: [ + { + find: "SCALE_DOWN:", + replacement: { + match: /!\(null==(\i)\|\|0===\i\|\|null==(\i)\|\|0===\i\)/, + replace: (_, width, height) => `!((null == ${width} || 0 === ${width}) && (null == ${height} || 0 === ${height}))` + } + } + ] +}); diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 5ec3c048..87847038 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -209,7 +209,7 @@ export default definePlugin({ }, get electronVersion() { - return VencordNative.native.getVersions().electron || window.armcord?.electron || null; + return VencordNative.native.getVersions().electron || window.legcord?.electron || null; }, get chromiumVersion() { diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index dd039cd3..248da3d6 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -75,7 +75,7 @@ async function generateDebugInfoMessage() { if (IS_DISCORD_DESKTOP) return `Discord Desktop v${DiscordNative.app.getVersion()}`; if (IS_VESKTOP) return `Vesktop v${VesktopNative.app.getVersion()}`; if (IS_EQUIBOP) return `Equibop v${VesktopNative.app.getVersion()}`; - if ("armcord" in window) return `ArmCord v${window.armcord.version}`; + if ("legcord" in window) return `LegCord v${window.armcord.version}`; // @ts-expect-error const name = typeof unsafeWindow !== "undefined" ? "UserScript" : "Web"; diff --git a/src/plugins/arRPC.web/index.tsx b/src/plugins/arRPC.web/index.tsx index 04289e57..6eec3f52 100644 --- a/src/plugins/arRPC.web/index.tsx +++ b/src/plugins/arRPC.web/index.tsx @@ -73,8 +73,8 @@ export default definePlugin({ }, async start() { - // ArmCord comes with its own arRPC implementation, so this plugin just confuses users - if ("armcord" in window) return; + // Legcord comes with its own arRPC implementation, so this plugin just confuses users + if ("legcord" in window) return; if (ws) ws.close(); ws = new WebSocket("ws://127.0.0.1:1337"); // try to open WebSocket diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx index dc4e68fe..687eded9 100644 --- a/src/plugins/betterRoleContext/index.tsx +++ b/src/plugins/betterRoleContext/index.tsx @@ -99,7 +99,11 @@ export default definePlugin({ id="vc-view-role-icon" label="View Role Icon" action={() => { - openImageModal(`${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${role.id}/${role.icon}.${settings.store.roleIconFileFormat}`); + openImageModal({ + url: `${location.protocol}//${window.GLOBAL_ENV.CDN_HOST}/role-icons/${role.id}/${role.icon}.${settings.store.roleIconFileFormat}`, + height: 128, + width: 128 + }); }} icon={ImageIcon} /> diff --git a/src/plugins/biggerStreamPreview/index.tsx b/src/plugins/biggerStreamPreview/index.tsx index 17296789..c5cff9bd 100644 --- a/src/plugins/biggerStreamPreview/index.tsx +++ b/src/plugins/biggerStreamPreview/index.tsx @@ -57,7 +57,11 @@ export const handleViewPreview = async ({ guildId, channelId, ownerId }: Applica const previewUrl = await ApplicationStreamPreviewStore.getPreviewURL(guildId, channelId, ownerId); if (!previewUrl) return; - openImageModal(previewUrl); + openImageModal({ + url: previewUrl, + height: 720, + width: 1280 + }); }; export const addViewStreamContext: NavContextMenuPatchCallback = (children, { userId }: { userId: string | bigint; }) => { diff --git a/src/plugins/imageZoom/index.tsx b/src/plugins/imageZoom/index.tsx index c789157c..87a5bd13 100644 --- a/src/plugins/imageZoom/index.tsx +++ b/src/plugins/imageZoom/index.tsx @@ -181,13 +181,6 @@ export default definePlugin({ replace: "$&$self.unMountMagnifier();" } ] - }, - { - find: ".carouselModal", - replacement: { - match: /(?<=\.carouselModal.{0,100}onClick:)\i,/, - replace: "()=>{}," - } } ], diff --git a/src/plugins/imageZoom/styles.css b/src/plugins/imageZoom/styles.css index 967fbf25..b2788b00 100644 --- a/src/plugins/imageZoom/styles.css +++ b/src/plugins/imageZoom/styles.css @@ -21,12 +21,3 @@ /* https://googlechrome.github.io/samples/image-rendering-pixelated/index.html */ } - -/* make the carousel take up less space so we can click the backdrop and exit out of it */ -[class*="modalCarouselWrapper_"] { - top: 0 !important; -} - -[class*="carouselModal_"] { - height: 0 !important; -} diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index ec52b406..a4f690af 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -28,7 +28,7 @@ const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel"); const UserUtils = findByPropsLazy("getGlobalName"); const ProfileListClasses = findByPropsLazy("emptyIconFriends", "emptyIconGuilds"); -const ExpandableList = findComponentByCodeLazy(".mutualFriendItem]"); +const ExpandableList = findComponentByCodeLazy('"PRESS_SECTION"'); const GuildLabelClasses = findByPropsLazy("guildNick", "guildAvatarWithoutIcon"); function getGroupDMName(channel: Channel) { @@ -142,16 +142,15 @@ export default definePlugin({ const mutualGDms = getMutualGroupDms(user.id); if (mutualGDms.length === 0) return null; - const header = getMutualGDMCountText(user); return ( <> {Divider} { })} + listClassName={listStyle} + header={"Mutual Groups"} + isLoading={false} + items={renderClickableGDMs(mutualGDms, () => { })} /> ); diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 576980cb..1e4f3041 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -91,15 +91,6 @@ export default definePlugin({ replace: "async function $1 if(await $self.handleLink(...arguments)) return;" } }, - // Make Spotify profile activity links open in app on web - { - find: "WEB_OPEN(", - predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify, - replacement: { - match: /\i\.\i\.isProtocolRegistered\(\)(.{0,100})window.open/g, - replace: "true$1VencordNative.native.openExternal" - } - }, { find: "no artist ids in metadata", predicate: () => !IS_DISCORD_DESKTOP && pluginSettings.store.spotify, diff --git a/src/plugins/serverInfo/GuildInfoModal.tsx b/src/plugins/serverInfo/GuildInfoModal.tsx index d0ede9c5..a0d138cd 100644 --- a/src/plugins/serverInfo/GuildInfoModal.tsx +++ b/src/plugins/serverInfo/GuildInfoModal.tsx @@ -80,7 +80,10 @@ function GuildInfoModal({ guild }: GuildProps) { className={cl("banner")} src={bannerUrl} alt="" - onClick={() => openImageModal(bannerUrl)} + onClick={() => openImageModal({ + url: bannerUrl, + width: 1024 + })} /> )} @@ -89,8 +92,10 @@ function GuildInfoModal({ guild }: GuildProps) { ? openImageModal(iconUrl, { - width: 256 + onClick={() => openImageModal({ + url: iconUrl, + height: 512, + width: 512, })} /> :
{guild.acronym}
@@ -153,7 +158,15 @@ function Owner(guildId: string, owner: User) { return (
- openImageModal(ownerAvatarUrl)} /> + openImageModal({ + url: ownerAvatarUrl, + height: 512, + width: 512 + })} + /> {Parser.parse(`<@${owner.id}>`)}
); diff --git a/src/plugins/serverInfo/index.tsx b/src/plugins/serverInfo/index.tsx index 7a6fa62c..df87a5f2 100644 --- a/src/plugins/serverInfo/index.tsx +++ b/src/plugins/serverInfo/index.tsx @@ -30,8 +30,8 @@ export default definePlugin({ name: "ServerInfo", description: "Allows you to view info about a server", authors: [Devs.Ven, Devs.Nuckyz], + dependencies: ["DynamicImageModalAPI"], tags: ["guild", "info", "ServerProfile"], - dependencies: ["ImageModalAPI"], contextMenus: { "guild-context": Patch, "guild-header-popout": Patch diff --git a/src/plugins/spotifyControls/PlayerComponent.tsx b/src/plugins/spotifyControls/PlayerComponent.tsx index aef0c736..41e09c16 100644 --- a/src/plugins/spotifyControls/PlayerComponent.tsx +++ b/src/plugins/spotifyControls/PlayerComponent.tsx @@ -229,7 +229,7 @@ function AlbumContextMenu({ track }: { track: Track; }) { id="view-cover" label="View Album Cover" // trolley - action={() => openImageModal(track.album.image.url)} + action={() => openImageModal(track.album.image)} icon={ImageIcon} /> openImage(url, 512, 512); +const openBanner = (url: string) => openImage(url, 1024); + +function openImage(url: string, width: number, height?: number) { const format = url.startsWith("/") ? "png" : settings.store.format; const u = new URL(url, window.location.href); @@ -76,11 +79,13 @@ function openImage(url: string) { url = u.toString(); u.searchParams.set("size", "4096"); - const originalUrl = u.toString(); + const original = u.toString(); - openImageModal(url, { - original: originalUrl, - height: 256 + openImageModal({ + url, + original, + width, + height }); } @@ -93,14 +98,14 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U openImage(IconUtils.getUserAvatarURL(user, true))} + action={() => openAvatar(IconUtils.getUserAvatarURL(user, true))} icon={ImageIcon} /> {memberAvatar && ( openImage(IconUtils.getGuildMemberAvatarURLSimple({ + action={() => openAvatar(IconUtils.getGuildMemberAvatarURLSimple({ userId: user.id, avatar: memberAvatar, guildId: guildId!, @@ -126,7 +131,7 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon id="view-icon" label="View Icon" action={() => - openImage(IconUtils.getGuildIconURL({ + openAvatar(IconUtils.getGuildIconURL({ id, icon, canAnimate: true @@ -140,7 +145,7 @@ const GuildContext: NavContextMenuPatchCallback = (children, { guild }: GuildCon id="view-banner" label="View Banner" action={() => - openImage(IconUtils.getGuildBannerURL(guild, true)!) + openBanner(IconUtils.getGuildBannerURL(guild, true)!) } icon={ImageIcon} /> @@ -158,7 +163,7 @@ const GroupDMContext: NavContextMenuPatchCallback = (children, { channel }: Grou id="view-group-channel-icon" label="View Icon" action={() => - openImage(IconUtils.getChannelIconURL(channel)!) + openAvatar(IconUtils.getChannelIconURL(channel)!) } icon={ImageIcon} /> @@ -172,10 +177,12 @@ export default definePlugin({ description: "Makes avatars and banners in user profiles clickable, adds View Icon/Banner entries in the user, server and group channel context menu.", dependencies: ["ImageModalAPI"], tags: ["ImageUtilities"], + dependencies: ["DynamicImageModalAPI"], settings, - openImage, + openAvatar, + openBanner, contextMenus: { "user-context": UserContext, @@ -189,7 +196,7 @@ export default definePlugin({ find: ".overlay:void 0,status:", replacement: { match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",{...\2,/, - replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openImage($1)}," + replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openAvatar($1)}," }, all: true }, @@ -198,7 +205,7 @@ export default definePlugin({ find: 'backgroundColor:"COMPLETE"', replacement: { match: /(\.banner,.+?),style:{(?=.+?backgroundImage:null!=(\i)\?"url\("\.concat\(\2,)/, - replace: (_, rest, bannerSrc) => `${rest},onClick:()=>${bannerSrc}!=null&&$self.openImage(${bannerSrc}),style:{cursor:${bannerSrc}!=null?"pointer":void 0,` + replace: (_, rest, bannerSrc) => `${rest},onClick:()=>${bannerSrc}!=null&&$self.openBanner(${bannerSrc}),style:{cursor:${bannerSrc}!=null?"pointer":void 0,` } }, // Group DMs top small & large icon @@ -206,7 +213,7 @@ export default definePlugin({ find: /\.recipients\.length>=2(?! `${m},onClick:()=>$self.openImage(${iconUrl})` + replace: (m, iconUrl) => `${m},onClick:()=>$self.openAvatar(${iconUrl})` } }, // User DMs top small icon @@ -214,7 +221,7 @@ export default definePlugin({ find: ".cursorPointer:null,children", replacement: { match: /.Avatar,.+?src:(.+?\))(?=[,}])/, - replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})` + replace: (m, avatarUrl) => `${m},onClick:()=>$self.openAvatar(${avatarUrl})` } }, // User Dms top large icon @@ -222,7 +229,7 @@ export default definePlugin({ find: 'experimentLocation:"empty_messages"', replacement: { match: /.Avatar,.+?src:(.+?\))(?=[,}])/, - replace: (m, avatarUrl) => `${m},onClick:()=>$self.openImage(${avatarUrl})` + replace: (m, avatarUrl) => `${m},onClick:()=>$self.openAvatar(${avatarUrl})` } } ] diff --git a/src/plugins/webKeybinds.web/index.ts b/src/plugins/webKeybinds.web/index.ts index 3357c78f..ea5ebb54 100644 --- a/src/plugins/webKeybinds.web/index.ts +++ b/src/plugins/webKeybinds.web/index.ts @@ -25,7 +25,7 @@ const KeyBinds = findByPropsLazy("JUMP_TO_GUILD", "SERVER_NEXT"); export default definePlugin({ name: "WebKeybinds", - description: "Re-adds keybinds missing in the web version of Discord: ctrl+t, ctrl+shift+t, ctrl+tab, ctrl+shift+tab, ctrl+1-9, ctrl+,. Only works fully on Vesktop/ArmCord, not inside your browser", + description: "Re-adds keybinds missing in the web version of Discord: ctrl+t, ctrl+shift+t, ctrl+tab, ctrl+shift+tab, ctrl+1-9, ctrl+,. Only works fully on Vesktop/Legcord, not inside your browser", authors: [Devs.Ven], enabledByDefault: true, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e3ed3675..bb2dc56f 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -928,6 +928,10 @@ export const EquicordDevs = Object.freeze({ name: "Leko", id: 108153734541942784n }, + SomeAspy: { + name: "SomeAspy", + id: 516750892372852754n, + }, } satisfies Record); // iife so #__PURE__ works correctly diff --git a/src/utils/discord.css b/src/utils/discord.css index 410e0c67..54cb6040 100644 --- a/src/utils/discord.css +++ b/src/utils/discord.css @@ -1,3 +1,25 @@ -.vc-imagemodal-fix { + +.vc-position-inherit { position: inherit; } + +/** + * copy pasted from discord css. not really webpack-findable since it's the only class in the module +**/ + +.vc-image-modal { + background: transparent!important; + box-shadow: none!important; + display: flex; + justify-content: center; + align-items: center; + border-radius: 0 +} + +@media(width <= 485px) { + .vc-image-modal { + display:relative; + overflow: visible; + overflow: initial + } +} diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index eae5e0e7..08de22cc 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -19,10 +19,10 @@ import "./discord.css"; import { MessageObject } from "@api/MessageEvents"; -import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MessageActions, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Channel, Guild, Message, User } from "discord-types/general"; -import { ImageModal, openModal } from "./modal"; +import { ImageModal, ImageModalItem, openModal } from "./modal"; /** * Open the invite modal @@ -110,23 +110,23 @@ export function sendMessage( return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra); } -const FIX_CLASS_NAME = "vc-imagemodal-fix"; - -export function openImageModal(url: string, props?: Partial>): string { +/** + * You must specify either height or width + */ +export function openImageModal(props: Omit): string { return openModal(modalProps => ( } - // Don't render forward message button scaleDown_f97a12 contain_f97a12 - renderForwardComponent={() => null} - shouldHideMediaOptions={false} - shouldAnimate={true} - fit={FIX_CLASS_NAME} + className="vc-image-modal" + fit="vc-position-inherit" items={[{ - ...props, type: "IMAGE", - url, + original: props.url, + ...props, }]} + onClose={modalProps.onClose} + shouldHideMediaOptions={false} + shouldAnimate /> )); } diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index 8c6a68ce..7459379e 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -101,23 +101,21 @@ export const Modals = findByPropsLazy("ModalRoot", "ModalCloseButton") as { }>; }; -// FIXME: type this -export type ImageModal = any & ComponentType<{ - className?: string; - src: string; - placeholder: string; - original: string; +export interface ImageModalItem { + type: "IMAGE" | "VIDEO"; + url: string; width?: number; height?: number; - animated?: boolean; - responsive?: boolean; - renderLinkComponent(props: any): ReactNode; - renderForwardComponent(props: any): ReactNode; - maxWidth?: number; - maxHeight?: number; - shouldAnimate?: boolean; + original?: string; +} + +export type ImageModal = ComponentType<{ + className?: string; + fit?: string; onClose?(): void; shouldHideMediaOptions?: boolean; + shouldAnimate?: boolean; + items: ImageModalItem[]; }>; export const ImageModal = findComponentByCodeLazy(".MEDIA_MODAL_CLOSE") as ImageModal;