From 7206502f4d3e69ec5fa5493e82c2cdd1b0a6121b Mon Sep 17 00:00:00 2001 From: thororen1234 <78185467+thororen1234@users.noreply.github.com> Date: Wed, 29 Jan 2025 08:46:10 -0500 Subject: [PATCH] Remove FakeProfileThemesAndEffects --- README.md | 3 +- .../components/BookmarkContainer.tsx | 23 +- .../channelTabs/components/ChannelTab.tsx | 7 +- .../components/ChannelTabsContainer.tsx | 21 +- .../util/{constants.ts => constants.tsx} | 20 +- .../components/Builder.tsx | 109 ---------- .../components/BuilderButton.tsx | 63 ------ .../components/BuilderColorButton.tsx | 41 ---- .../components/index.tsx | 99 --------- .../components/settingsAboutComponent.tsx | 29 --- .../fakeProfileThemesAndEffects/index.tsx | 205 ------------------ .../fakeProfileThemesAndEffects/lib/ftpe.ts | 205 ------------------ .../fakeProfileThemesAndEffects/lib/index.ts | 10 - .../lib/profileEffects.ts | 72 ------ .../lib/profilePreview.ts | 77 ------- .../lib/userProfile.ts | 69 ------ src/equicordplugins/homeTyping/index.tsx | 5 +- .../limitMiddleClickPaste/index.ts | 12 +- src/equicordplugins/pinIcon/index.tsx | 2 +- .../unreadBadgeCount/index.tsx | 27 ++- 20 files changed, 94 insertions(+), 1005 deletions(-) rename src/equicordplugins/channelTabs/util/{constants.ts => constants.tsx} (81%) delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/components/Builder.tsx delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderButton.tsx delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderColorButton.tsx delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/components/index.tsx delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/components/settingsAboutComponent.tsx delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/index.tsx delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/lib/ftpe.ts delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/lib/index.ts delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/lib/profileEffects.ts delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/lib/profilePreview.ts delete mode 100644 src/equicordplugins/fakeProfileThemesAndEffects/lib/userProfile.ts diff --git a/README.md b/README.md index 32969b6b..c9e51a71 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch ### Extra included plugins
-148 additional plugins +147 additional plugins ### All Platforms - AllCallTimers by MaxHerbold & D3SOX @@ -51,7 +51,6 @@ You can join our [discord server](https://discord.gg/5Xh2W87egW) for commits, ch - Encryptcord by Inbestigator - EquicordCSS by thororen, Panniku, Dablulite, Coolesding, MiniDiscordThemes, LuckFire, gold_me - ExportContacts by dat_insanity -- FakeProfileThemesAndEffects by ryan - FindReply by newwares - FixFileExtensions by thororen - FrequentQuickSwitcher by Samwich diff --git a/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx b/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx index ecc1f538..fcacd0af 100644 --- a/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx +++ b/src/equicordplugins/channelTabs/components/BookmarkContainer.tsx @@ -8,7 +8,6 @@ import { classNameFactory } from "@api/Styles"; import { getIntlMessage } from "@utils/discord"; import { classes } from "@utils/misc"; import { closeModal, openModal } from "@utils/modal"; -import { findByPropsLazy } from "@webpack"; import { Avatar, ChannelStore, ContextMenuApi, FluxDispatcher, GuildStore, Menu, ReadStateStore, ReadStateUtils, Text, Tooltip, useDrag, useDrop, useEffect, useRef, UserStore } from "@webpack/common"; import { BasicChannelTabsProps, Bookmark, BookmarkFolder, BookmarkProps, CircleQuestionIcon, isBookmarkFolder, settings, switchChannel, useBookmarks } from "../util"; @@ -17,7 +16,23 @@ import { BookmarkContextMenu, EditModal } from "./ContextMenus"; const cl = classNameFactory("vc-channeltabs-"); -const { StarIcon } = findByPropsLazy("StarIcon"); +function StarIcon({ className = "", ...props }) { + return + + ; +} function FolderIcon({ fill }: { fill: string; }) { return ( @@ -289,9 +304,7 @@ export default function BookmarkContainer(props: BasicChannelTabsProps & { userI }} > } diff --git a/src/equicordplugins/channelTabs/components/ChannelTab.tsx b/src/equicordplugins/channelTabs/components/ChannelTab.tsx index d1a337cf..9c70b22d 100644 --- a/src/equicordplugins/channelTabs/components/ChannelTab.tsx +++ b/src/equicordplugins/channelTabs/components/ChannelTab.tsx @@ -15,10 +15,11 @@ import { ChannelTabsProps, CircleQuestionIcon, closeTab, isTabSelected, moveDrag import { TabContextMenu } from "./ContextMenus"; const ThreeDots = findComponentByCodeLazy(".dots,", "dotRadius:"); -const { getBadgeWidthForValue } = findByPropsLazy("getBadgeWidthForValue"); const dotStyles = findByPropsLazy("numberBadge", "textBadge"); -const { FriendsIcon } = findByPropsLazy("FriendsIcon"); +function FriendsIcon() { + return ; +} const ChannelTypeIcon = findComponentByCodeLazy(".iconContainerWithGuildIcon,"); const cl = classNameFactory("vc-channeltabs-"); @@ -71,7 +72,7 @@ export const NotificationDot = ({ channelIds }: { channelIds: string[]; }) => { data-has-mention={!!mentionCount} className={classes(dotStyles.numberBadge, dotStyles.baseShapeRound)} style={{ - width: getBadgeWidthForValue(mentionCount || unreadCount) + width: 16 }} ref={node => node?.style.setProperty("background-color", mentionCount ? "var(--red-400)" : "var(--brand-500)", "important" diff --git a/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx b/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx index b1181b53..91de3840 100644 --- a/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx +++ b/src/equicordplugins/channelTabs/components/ChannelTabsContainer.tsx @@ -6,7 +6,6 @@ import { classNameFactory } from "@api/Styles"; import { useForceUpdater } from "@utils/react"; -import { findByPropsLazy } from "@webpack"; import { Button, ContextMenuApi, Flex, FluxDispatcher, Forms, useCallback, useEffect, useRef, UserStore, useState } from "@webpack/common"; import { BasicChannelTabsProps, ChannelTabsProps, createTab, handleChannelSwitch, openedTabs, openStartupTabs, saveTabs, settings, setUpdaterFunction, useGhostTabs } from "../util"; @@ -16,7 +15,23 @@ import { BasicContextMenu } from "./ContextMenus"; type TabSet = Record; -const { PlusSmallIcon } = findByPropsLazy("PlusSmallIcon"); +function PlusSmallIcon() { + return + + + ; +} + const cl = classNameFactory("vc-channeltabs-"); export default function ChannelsTabsContainer(props: BasicChannelTabsProps) { @@ -75,7 +90,7 @@ export default function ChannelsTabsContainer(props: BasicChannelTabsProps) { onClick={() => createTab(props, true)} className={cl("button", "new-button", "hoverable")} > - + {GhostTabs} diff --git a/src/equicordplugins/channelTabs/util/constants.ts b/src/equicordplugins/channelTabs/util/constants.tsx similarity index 81% rename from src/equicordplugins/channelTabs/util/constants.ts rename to src/equicordplugins/channelTabs/util/constants.tsx index 45491dc8..10aba4fe 100644 --- a/src/equicordplugins/channelTabs/util/constants.ts +++ b/src/equicordplugins/channelTabs/util/constants.tsx @@ -7,7 +7,6 @@ import { definePluginSettings } from "@api/Settings"; import { Logger } from "@utils/Logger"; import { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; import { ChannelTabsPreview } from "../components/ChannelTabsContainer"; @@ -74,4 +73,21 @@ export const settings = definePluginSettings({ } }); -export const { CircleQuestionIcon } = findByPropsLazy("CircleQuestionIcon"); +export function CircleQuestionIcon({ height = 24, width = 24 }) { + return + + + + ; + +} diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/components/Builder.tsx b/src/equicordplugins/fakeProfileThemesAndEffects/components/Builder.tsx deleted file mode 100644 index 349e0a22..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/components/Builder.tsx +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { copyWithToast } from "@utils/misc"; -import { Button, showToast, Switch, UserStore, useState, useToken } from "@webpack/common"; -import type { Guild } from "discord-types/general"; - -import { buildFPTE, useAccentColor, usePrimaryColor, useProfileEffect, useShowPreview } from "../lib"; -import { BuilderButton, BuilderColorButton, CustomizationSection, openProfileEffectModal, tokens, useAvatarColors } from "."; - -export interface BuilderProps { - guild?: Guild | undefined; -} - -export function Builder({ guild }: BuilderProps) { - const [primaryColor, setPrimaryColor] = usePrimaryColor(null); - const [accentColor, setAccentColor] = useAccentColor(null); - const [effect, setEffect] = useProfileEffect(null); - const [preview, setPreview] = useShowPreview(true); - const [buildLegacy, setBuildLegacy] = useState(false); - - const avatarColors = useAvatarColors( - UserStore.getCurrentUser()?.getAvatarURL(guild?.id, 80), - useToken(tokens.unsafe_rawColors.PRIMARY_530).hex(), - false - ); - - return ( - <> - -
- - - -
- - -
-
-
- - FPTE Builder Preview - - - Build backwards compatible FPTE - - - ); -} diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderButton.tsx b/src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderButton.tsx deleted file mode 100644 index 9da8049b..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderButton.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { Text, Tooltip } from "@webpack/common"; -import type { ComponentProps } from "react"; - -export interface BuilderButtonProps { - label?: string | undefined; - tooltip?: string | undefined; - selectedStyle?: ComponentProps<"div">["style"]; - buttonProps?: ComponentProps<"div"> | undefined; -} - -export const BuilderButton = ({ label, tooltip, selectedStyle, buttonProps }: BuilderButtonProps) => ( - - {tooltipProps => ( -
-
- {!selectedStyle && ( - - - - )} -
- {!!label && ( - - {label} - - )} -
- )} -
-); diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderColorButton.tsx b/src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderColorButton.tsx deleted file mode 100644 index e29357a5..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/components/BuilderColorButton.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { Popout } from "@webpack/common"; - -import { BuilderButton, type BuilderButtonProps, CustomColorPicker, type CustomColorPickerProps } from "."; - -export interface BuilderColorButtonProps extends Pick, Pick { - color: number | null; - setColor: (color: number | null) => void; -} - -export const BuilderColorButton = ({ label, color, setColor, suggestedColors }: BuilderColorButtonProps) => ( - ( - - )} - > - {popoutProps => { - const hexColor = color ? "#" + color.toString(16).padStart(6, "0") : undefined; - - return ( - - ); - }} - -); diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/components/index.tsx b/src/equicordplugins/fakeProfileThemesAndEffects/components/index.tsx deleted file mode 100644 index b08aa00b..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/components/index.tsx +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { type ModalProps, openModal } from "@utils/modal"; -import { extractAndLoadChunksLazy, findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; -import type { useToken } from "@webpack/types"; -import type { Guild } from "discord-types/general"; -import type { ComponentType, FunctionComponent, PropsWithChildren, ReactNode } from "react"; - -import type { ProfileEffectConfig } from "../lib"; - -export * from "./Builder"; -export * from "./BuilderButton"; -export * from "./BuilderColorButton"; -export * from "./settingsAboutComponent"; - -export interface CustomizationSectionProps extends PropsWithChildren { - borderType?: FeatureBorderType | undefined; - className?: string | undefined; - description?: ReactNode; - disabled?: boolean | undefined /* = false */; - errors?: string[] | undefined; - forcedDivider?: boolean | undefined /* = false */; - hasBackground?: boolean | undefined /* = false */; - hideDivider?: boolean | undefined /* = false */; - showBorder?: boolean | undefined /* = false */; - showPremiumIcon?: boolean | undefined /* = false */; - title?: ReactNode; - titleIcon?: ReactNode; - titleId?: string | undefined; -} - -// Original name: FeatureBorderTypes -export const enum FeatureBorderType { - LIMITED = "limited", - PREMIUM = "premium", -} - -export const CustomizationSection: ComponentType - = findByCodeLazy(".customizationSectionBackground"); - -export const tokens: { - unsafe_rawColors: Record[0]>; -} = findByPropsLazy("unsafe_rawColors", "modules"); - -export const useAvatarColors: ( - avatarURL: string | null | undefined, - fallbackColor: string, - desaturateColors?: boolean | undefined /* = true */ -) => [string, string, ...string[]] = findByCodeLazy(".palette[", ".desaturateUserColors"); - -export interface CustomColorPickerProps { - className?: string | undefined; - eagerUpdate?: boolean | undefined /* = false */; - footer?: ReactNode; - middle?: ReactNode; - onChange: (color: number) => void; - onClose?: (() => void) | undefined; - showEyeDropper?: boolean | undefined /* = false */; - suggestedColors?: string[] | null | undefined; - wrapperComponentType?: ComponentType | null | undefined; - value?: string | number | null | undefined; -} - -export const CustomColorPicker = findComponentByCodeLazy(".customColorPicker"); - -interface ProfileEffectModalProps extends ModalProps { - analyticsLocations?: string[] | undefined; - guild?: Guild | null | undefined; - initialSelectedEffectId?: string | undefined; - onApply: (effect: ProfileEffectConfig | null) => void; -} - -let ProfileEffectModal: FunctionComponent = () => null; - -export function setProfileEffectModal(comp: typeof ProfileEffectModal) { - ProfileEffectModal = comp; -} - -const requireProfileEffectModal = extractAndLoadChunksLazy(["initialSelectedEffectId:", ".openModalLazy"]); - -export async function openProfileEffectModal( - initialEffectId: ProfileEffectModalProps["initialSelectedEffectId"], - onApply: ProfileEffectModalProps["onApply"], - guild?: ProfileEffectModalProps["guild"] -) { - await requireProfileEffectModal(); - openModal(modalProps => ( - - )); -} diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/components/settingsAboutComponent.tsx b/src/equicordplugins/fakeProfileThemesAndEffects/components/settingsAboutComponent.tsx deleted file mode 100644 index 7f8b1f58..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/components/settingsAboutComponent.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { Margins } from "@utils/margins"; -import { Forms } from "@webpack/common"; - -export const settingsAboutComponent = () => ( - - Usage - - After enabling this plugin, you will see custom theme colors and effects in the profiles of others using this plugin. -
- To set your own profile theme colors and effect: -
-
    -
  1. Go to your profile settings
  2. -
  3. Use the FPTE Builder to choose your profile theme colors and effect
  4. -
  5. Click the "Copy FPTE" button
  6. -
  7. Paste the invisible text anywhere in your About Me
  8. -
-
-
-); diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/index.tsx b/src/equicordplugins/fakeProfileThemesAndEffects/index.tsx deleted file mode 100644 index ac6b3b25..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/index.tsx +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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 { EquicordDevs } from "@utils/constants"; -import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; -import definePlugin, { OptionType } from "@utils/types"; -import { useMemo } from "@webpack/common"; - -import { Builder, type BuilderProps, setProfileEffectModal, settingsAboutComponent } from "./components"; -import { ProfileEffectRecord, ProfileEffectStore } from "./lib/profileEffects"; -import { profilePreviewHook } from "./lib/profilePreview"; -import { decodeAboutMeFPTEHook } from "./lib/userProfile"; - -function replaceHelper( - string: string, - replaceArgs: readonly (readonly [searchRegExp: RegExp, replaceString: string])[] -) { - let result = string; - for (const [searchRegExp, replaceString] of replaceArgs) { - const beforeReplace = result; - result = result.replace( - canonicalizeMatch(searchRegExp), - canonicalizeReplace(replaceString, "FakeProfileThemesAndEffects") - ); - if (beforeReplace === result) - throw new Error("Replace had no effect: " + searchRegExp); - } - return result; -} - -export const settings = definePluginSettings({ - prioritizeNitro: { - description: "Source to prioritize", - type: OptionType.SELECT, - options: [ - { label: "Nitro", value: true }, - { label: "About Me", value: false, default: true } - ] - }, - hideBuilder: { - description: "Hide the FPTE Builder in the User Profile and Server Profiles settings pages", - type: OptionType.BOOLEAN, - default: false - } -}); - -export default definePlugin({ - name: "FakeProfileThemesAndEffects", - description: "Allows profile theming and the usage of profile effects by hiding the colors and effect ID in your About Me using invisible, zero-width characters", - authors: [EquicordDevs.ryan], - patches: [ - // Patches UserProfileStore.getUserProfile - { - find: '"UserProfileStore"', - replacement: { - match: /([{}]getUserProfile\([^)]*\){return) ?([^}]+)/, - replace: "$1 $self.decodeAboutMeFPTEHook($2)" - } - }, - // Patches ProfileCustomizationPreview - { - find: ".EDIT_PROFILE_BANNER})", - replacement: { - match: /:function\(\){return (\i)}.+function \1\((\i)\){/, - replace: "$&$self.profilePreviewHook($2);" - } - }, - // Adds the FPTE Builder to the User Profile settings page - { - find: '"DefaultCustomizationSections"', - replacement: { - match: /\.sectionsContainer,.*?children:\[/, - replace: "$&$self.addFPTEBuilder()," - } - }, - // Adds the FPTE Builder to the Server Profiles settings page - { - find: '"guild should not be null"', - replacement: { - match: /\.sectionsContainer,.*?children:\[(?=.+?[{,]guild:(\i))/, - replace: "$&$self.addFPTEBuilder($1)," - } - }, - // ProfileEffectModal - { - find: "initialSelectedProfileEffectId:", - group: true, - replacement: [ - // Modal root - { - match: /(function (\i)\([^)]*\){(?:.(?!function |}$))*\.ModalRoot,(?:.(?!function |}$))*}).*(?=})/, - replace: (match, func, funcName) => `${match}(()=>{$self.ProfileEffectModal=${funcName};` - + replaceHelper(func, [ - // Required for the profile preview to show profile effects - [ - /(?<=[{,]purchases:.+?}=).+?(?=,\i=|,{\i:|;)/, - "{isFetching:!1,categories:new Map,purchases:$self.usePurchases()}" - ] - ]) - + "})()" - }, - // Modal content - { - match: /(function \i\([^)]*\){(?:.(?!function ))*\.ModalContent,(?:.(?!function ))*}).*(?=}\))/, - replace: (match, func) => match + replaceHelper(func, [ - // Required to show the apply button - [ - /(?<=[{,]purchase:.+?}=).+?(?=,\i=|,{\i:|;)/, - "{purchase:{purchasedAt:new Date}}" - ], - // Replaces the profile effect list with the modified version - [ - /(?<=\.jsxs?\)\()[^,]+(?=,{(?:(?:.(?!\.jsxs?\)))+,)?onSelect:)/, - "$self.ProfileEffectSelection" - ], - // Replaces the apply profile effect function with the modified version - [ - /(?<=[{,]onApply:).*?\)\((\i).*?(?=,\i:|}\))/, - "()=>$self.onApply($1)" - ], - // Required to show the apply button - [ - /(?<=[{,]canUseCollectibles:).+?(?=,\i:|}\))/, - "!0" - ], - // Required to enable the apply button - [ - /(?<=[{,]disableApplyButton:).+?(?=,\i:|}\))/, - "!1" - ] - ]) - } - ] - }, - // ProfileEffectSelection - { - find: ".presetEffectBackground", - replacement: { - match: /function\(\i,(\i),.+[,;}]\1\.\i=([^=].+?})(?=;|}$).*(?=}$)/, - replace: (match, _, func) => `${match};$self.ProfileEffectSelection=` - + replaceHelper(func, [ - // Removes the "Exclusive to Nitro" and "Preview The Shop" sections - // Adds every profile effect to the "Your Decorations" section and removes the "Shop" button - [ - /(?<=[ ,](\i)=).+?(?=(?:,\i=|,{\i:|;).+?:\1\.map\()/, - "$self.useProfileEffectSections($&)" - ] - ]) - } - }, - // Patches ProfileEffectPreview - { - find: ".effectDescriptionContainer", - replacement: { - // Add back removed "forProfileEffectModal" property - match: /(?<=[{,])(?=pendingProfileEffectId:)/, - replace: "forProfileEffectModal:!0," - } - } - ], - - addFPTEBuilder: (guild?: BuilderProps["guild"]) => settings.store.hideBuilder ? null : , - - onApply(_effectId?: string) { }, - set ProfileEffectModal(comp: Parameters[0]) { - setProfileEffectModal(props => { - this.onApply = effectId => { - props.onApply(effectId ? ProfileEffectStore.getProfileEffectById(effectId)!.config : null); - props.onClose(); - }; - return comp(props); - }); - }, - - ProfileEffectSelection: () => null, - - usePurchases: () => useMemo( - () => new Map(ProfileEffectStore.profileEffects.map(effect => [ - effect.id, - { items: new ProfileEffectRecord(effect) } - ])), - [ProfileEffectStore.profileEffects] - ), - - useProfileEffectSections: (origSections: Record[]) => useMemo( - () => { - origSections.splice(1); - origSections[0].items.splice(1); - for (const effect of ProfileEffectStore.profileEffects) - origSections[0].items.push(new ProfileEffectRecord(effect)); - return origSections; - }, - [ProfileEffectStore.profileEffects] - ), - - settings, - replaceHelper, - settingsAboutComponent, - decodeAboutMeFPTEHook, - profilePreviewHook -}); diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/lib/ftpe.ts b/src/equicordplugins/fakeProfileThemesAndEffects/lib/ftpe.ts deleted file mode 100644 index 54412ff4..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/lib/ftpe.ts +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -/** The FPTE delimiter codepoint (codepoint of zero-width space). */ -const DELIMITER_CODEPOINT = 0x200B; -/** The FPTE delimiter (zero-width space). */ -const DELIMITER = String.fromCodePoint(DELIMITER_CODEPOINT); -/** The FPTE radix (number of default-ignorable codepoints in the SSP plane). */ -const RADIX = 0x1000; -/** The FPTE starting codepoint (first codepoint in the SSP plane). */ -const STARTING_CODEPOINT = 0xE0000; -/** The FPTE starting character (first character in the SSP plane). */ -const STARTING = String.fromCodePoint(STARTING_CODEPOINT); -/** The FPTE ending codepoint (last default-ignorable codepoint in the SSP plane). */ -const ENDING_CODEPOINT = STARTING_CODEPOINT + RADIX - 1; - -/** - * Builds a theme color string in the legacy format: `[#primary,#accent]`, where primary and accent are - * 24-bit colors as base-16 strings, with each codepoint of the string offset by +{@link STARTING_CODEPOINT}. - * @param primary The 24-bit primary color. - * @param accent The 24-bit accent color. - * @returns The built legacy-format theme color string. - */ -export function encodeColorsLegacy(primary: number, accent: number) { - let str = ""; - for (const char of `[#${primary.toString(16)},#${accent.toString(16)}]`) - str += String.fromCodePoint(char.codePointAt(0)! + STARTING_CODEPOINT); - return str; -} - -/** - * Extracts the theme colors from a legacy-format string. - * @param str The legacy-format string to extract the theme colors from. - * @returns The profile theme colors. Colors will be -1 if not found. - * @see {@link encodeColorsLegacy} - */ -export function decodeColorsLegacy(str: string): [primaryColor: number, accentColor: number] { - const [primary, accent] = str.matchAll(/(?<=#)[\dA-Fa-f]{1,6}/g); - return [primary ? parseInt(primary[0], 16) : -1, accent ? parseInt(accent[0], 16) : -1]; -} - -/** - * Converts a 24-bit color to a base-{@link RADIX} string with each codepoint offset by +{@link STARTING_CODEPOINT}. - * @param color The 24-bit color to be converted. - * @returns The converted base-{@link RADIX} string with +{@link STARTING_CODEPOINT} offset. - */ -export function encodeColor(color: number) { - if (color === 0) return STARTING; - let str = ""; - for (; color > 0; color = Math.trunc(color / RADIX)) - str = String.fromCodePoint(color % RADIX + STARTING_CODEPOINT) + str; - return str; -} - -/** - * Converts a no-offset base-{@link RADIX} string to a 24-bit color. - * @param str The no-offset base-{@link RADIX} string to be converted. - * @returns The converted 24-bit color. - * Will be -1 if `str` is empty and -2 if the color is greater than the maximum 24-bit color, 0xFFFFFF. - */ -export function decodeColor(str: string) { - if (!str) return -1; - let color = 0; - for (let i = 0; i < str.length; i++) { - if (color > 0xFFF_FFF) return -2; - color += str.codePointAt(i)! * RADIX ** (str.length - 1 - i); - } - return color; -} - -/** - * Converts an effect ID to a base-{@link RADIX} string with each code point offset by +{@link STARTING_CODEPOINT}. - * @param id The effect ID to be converted. - * @returns The converted base-{@link RADIX} string with +{@link STARTING_CODEPOINT} offset. - */ -export function encodeEffect(id: bigint) { - if (id === 0n) return STARTING; - let str = ""; - for (; id > 0n; id /= BigInt(RADIX)) - str = String.fromCodePoint(Number(id % BigInt(RADIX)) + STARTING_CODEPOINT) + str; - return str; -} - -/** - * Converts a no-offset base-{@link RADIX} string to an effect ID. - * @param str The no-offset base-{@link RADIX} string to be converted. - * @returns The converted effect ID. - * Will be -1n if `str` is empty and -2n if the color is greater than the maximum effect ID. - */ -export function decodeEffect(str: string) { - if (!str) return -1n; - let id = 0n; - for (let i = 0; i < str.length; i++) { - if (id >= 10_000_000_000_000_000_000n) return -2n; - id += BigInt(str.codePointAt(i)!) * BigInt(RADIX) ** BigInt(str.length - 1 - i); - } - return id; -} - -/** - * Builds a FPTE string containing the given primary/accent colors and effect ID. If the FPTE Builder is NOT set to backwards - * compatibility mode, the primary and accent colors will be converted to base-{@link RADIX} before they are encoded. - * @param primary The primary profile theme color. Must be negative if unset. - * @param accent The accent profile theme color. Must be negative if unset. - * @param effect The profile effect ID. Must be empty if unset. - * @param legacy Whether the primary and accent colors should be legacy encoded. - * @returns The built FPTE string. Will be empty if the given colors and effect are all unset. - */ -export function buildFPTE(primary: number, accent: number, effect: string, legacy: boolean) { - /** The FPTE string to be returned. */ - let fpte = ""; - - // If the FPTE Builder is set to backwards compatibility mode, - // the primary and accent colors, if set, will be legacy encoded. - if (legacy) { - // Legacy FPTE strings must include both the primary and accent colors, even if they are the same. - - if (primary >= 0) { - // If both the primary and accent colors are set, they will be legacy encoded and added to the - // string; otherwise, if the accent color is unset, the primary color will be used in its place. - if (accent >= 0) - fpte = encodeColorsLegacy(primary, accent); - else - fpte = encodeColorsLegacy(primary, primary); - - // If the effect ID is set, it will be encoded and added to the string prefixed by one delimiter. - if (effect) - fpte += DELIMITER + encodeEffect(BigInt(effect)); - - return fpte; - } - - // Since the primary color is unset, the accent color, if set, will be used in its place. - if (accent >= 0) { - fpte = encodeColorsLegacy(accent, accent); - - // If the effect ID is set, it will be encoded and added to the string prefixed by one delimiter. - if (effect) - fpte += DELIMITER + encodeEffect(BigInt(effect)); - - return fpte; - } - } - // If the primary color is set, it will be encoded and added to the string. - else if (primary >= 0) { - fpte = encodeColor(primary); - - // If the accent color is set and different from the primary color, it - // will be encoded and added to the string prefixed by one delimiter. - if (accent >= 0 && primary !== accent) { - fpte += DELIMITER + encodeColor(accent); - - // If the effect ID is set, it will be encoded and added to the string prefixed by one delimiter. - if (effect) - fpte += DELIMITER + encodeEffect(BigInt(effect)); - - return fpte; - } - } - // If only the accent color is set, it will be encoded and added to the string. - else if (accent >= 0) - fpte = encodeColor(accent); - - // Since either the primary/accent colors are the same, both are unset, or just one is set, only one color will be added - // to the string; therefore, the effect ID, if set, will be encoded and added to the string prefixed by two delimiters. - if (effect) - fpte += DELIMITER + DELIMITER + encodeEffect(BigInt(effect)); - - return fpte; -} - -/** - * Extracts the delimiter-separated values of the first FPTE substring in a string. - * @param str The string to be searched for a FPTE substring. - * @returns An array of the found FPTE substring's extracted values. Values will be empty if not found. - */ -export function extractFPTE(str: string) { - /** The array of extracted FPTE values to be returned. */ - const fpte: [maybePrimaryOrLegacy: string, maybeAccentOrEffect: string, maybeEffect: string] = ["", "", ""]; - /** The current index of {@link fpte} getting extracted. */ - let i = 0; - - for (const char of str) { - /** The current character's codepoint. */ - const cp = char.codePointAt(0)!; - - // If the current character is a delimiter, then the current index of fpte has been completed. - if (cp === DELIMITER_CODEPOINT) { - // If the current index of fpte is the last, then the extraction is done. - if (i >= 2) break; - i++; // Start extracting the next index of fpte. - } - // If the current character is not a delimiter but a valid FPTE - // character, it will be added to the current index of fpte. - else if (cp >= STARTING_CODEPOINT && cp <= ENDING_CODEPOINT) - fpte[i] += String.fromCodePoint(cp - STARTING_CODEPOINT); - // If an FPTE string has been found and its end has been reached, then the extraction is done. - else if (i > 0 || fpte[0]) break; - } - - return fpte; -} diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/lib/index.ts b/src/equicordplugins/fakeProfileThemesAndEffects/lib/index.ts deleted file mode 100644 index 88f85ff6..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/lib/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -export * from "./ftpe"; -export * from "./profileEffects"; -export * from "./profilePreview"; -export * from "./userProfile"; diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/lib/profileEffects.ts b/src/equicordplugins/fakeProfileThemesAndEffects/lib/profileEffects.ts deleted file mode 100644 index bb789f3e..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/lib/profileEffects.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { findByCodeLazy, findStoreLazy } from "@webpack"; -import type { FluxStore } from "@webpack/types"; -import type { SnakeCasedProperties } from "type-fest"; - -export const ProfileEffectStore: FluxStore & { - canFetch: () => boolean; - getProfileEffectById: (effectId: string) => ProfileEffect | undefined; - hasFetched: () => boolean; - readonly fetchError: Error | undefined; - readonly isFetching: boolean; - readonly profileEffects: ProfileEffect[]; - readonly tryItOutId: string | null; -} = findStoreLazy("ProfileEffectStore"); - -export const ProfileEffectRecord: { - new(profileEffectProperties: ProfileEffectProperties): ProfileEffectRecordInstance; - fromServer: (profileEffectFromServer: SnakeCasedProperties) => ProfileEffectRecordInstance; -} = findByCodeLazy(",this.type=", ".PROFILE_EFFECT"); - -export type ProfileEffectProperties = Omit; - -export interface ProfileEffectRecordInstance { - id: string; - skuId: string; - type: CollectiblesItemType.PROFILE_EFFECT; -} - -export interface ProfileEffect { - config: ProfileEffectConfig; - id: string; - skuId: string; -} - -export interface ProfileEffectConfig { - accessibilityLabel: string; - animationType: number; - description: string; - effects: { - duartion: number; - height: number; - loop: boolean; - loopDelay: number; - position: { - x: number; - y: number; - }; - src: string; - start: number; - width: number; - zIndex: number; - }[]; - id: string; - reducedMotionSrc: string; - sku_id: string; - staticFrameSrc?: string; - thumbnailPreviewSrc: string; - title: string; - type: CollectiblesItemType.PROFILE_EFFECT; -} - -export const enum CollectiblesItemType { - AVATAR_DECORATION = 0, - PROFILE_EFFECT = 1, - NONE = 100, - BUNDLE = 1_000, -} diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/lib/profilePreview.ts b/src/equicordplugins/fakeProfileThemesAndEffects/lib/profilePreview.ts deleted file mode 100644 index 8a0a4dce..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/lib/profilePreview.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { FluxDispatcher, useState } from "@webpack/common"; - -import type { ProfileEffectConfig } from "./profileEffects"; - -function updatePreview() { - FluxDispatcher.dispatch({ type: "USER_SETTINGS_ACCOUNT_SUBMIT_SUCCESS" }); -} - -let primaryColor: number | null = null; -export function usePrimaryColor(initialState: typeof primaryColor) { - const [state, setState] = useState(() => primaryColor = initialState); - return [ - state, - (color: typeof primaryColor) => { - setState(primaryColor = color); - if (showPreview) updatePreview(); - } - ] as const; -} - -let accentColor: number | null = null; -export function useAccentColor(initialState: typeof accentColor) { - const [state, setState] = useState(() => accentColor = initialState); - return [ - state, - (color: typeof accentColor) => { - setState(accentColor = color); - if (showPreview) updatePreview(); - } - ] as const; -} - -let profileEffect: ProfileEffectConfig | null = null; -export function useProfileEffect(initialState: typeof profileEffect) { - const [state, setState] = useState(() => profileEffect = initialState); - return [ - state, - (effect: typeof profileEffect) => { - setState(profileEffect = effect); - if (showPreview) updatePreview(); - } - ] as const; -} - -let showPreview = true; -export function useShowPreview(initialState: typeof showPreview) { - const [state, setState] = useState(() => showPreview = initialState); - return [ - state, - (preview: typeof showPreview) => { - setState(showPreview = preview); - updatePreview(); - } - ] as const; -} - -export function profilePreviewHook(props: Record) { - if (showPreview) { - if (primaryColor !== null) { - props.pendingThemeColors = [primaryColor, accentColor ?? primaryColor]; - props.canUsePremiumCustomization = true; - } else if (accentColor !== null) { - props.pendingThemeColors = [accentColor, accentColor]; - props.canUsePremiumCustomization = true; - } - if (!props.forProfileEffectModal && profileEffect) { - props.pendingProfileEffectId = profileEffect.id; - props.canUsePremiumCustomization = true; - } - } -} diff --git a/src/equicordplugins/fakeProfileThemesAndEffects/lib/userProfile.ts b/src/equicordplugins/fakeProfileThemesAndEffects/lib/userProfile.ts deleted file mode 100644 index bd91c81f..00000000 --- a/src/equicordplugins/fakeProfileThemesAndEffects/lib/userProfile.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Vencord, a Discord client mod - * Copyright (c) 2024 Vendicated and contributors - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -import { settings } from ".."; -import { decodeColor, decodeColorsLegacy, decodeEffect, extractFPTE } from "."; - -export interface UserProfile { - bio: string; - premiumType: number | null | undefined; - profileEffectId: string | undefined; - themeColors: [primaryColor: number, accentColor: number] | undefined; -} - -function updateProfileThemeColors(profile: UserProfile, primary: number, accent: number) { - if (primary > -1) { - profile.themeColors = [primary, accent > -1 ? accent : primary]; - profile.premiumType = 2; - } else if (accent > -1) { - profile.themeColors = [accent, accent]; - profile.premiumType = 2; - } -} - -function updateProfileEffectId(profile: UserProfile, id: bigint) { - if (id > -1n) { - profile.profileEffectId = id.toString(); - profile.premiumType = 2; - } -} - -export function decodeAboutMeFPTEHook(profile?: UserProfile) { - if (!profile) return profile; - - if (settings.store.prioritizeNitro) { - if (profile.themeColors) { - if (!profile.profileEffectId) { - const fpte = extractFPTE(profile.bio); - if (decodeColor(fpte[0]) === -2) - updateProfileEffectId(profile, decodeEffect(fpte[1])); - else - updateProfileEffectId(profile, decodeEffect(fpte[2])); - } - return profile; - } else if (profile.profileEffectId) { - const fpte = extractFPTE(profile.bio); - const primaryColor = decodeColor(fpte[0]); - if (primaryColor === -2) - updateProfileThemeColors(profile, ...decodeColorsLegacy(fpte[0])); - else - updateProfileThemeColors(profile, primaryColor, decodeColor(fpte[1])); - return profile; - } - } - - const fpte = extractFPTE(profile.bio); - const primaryColor = decodeColor(fpte[0]); - if (primaryColor === -2) { - updateProfileThemeColors(profile, ...decodeColorsLegacy(fpte[0])); - updateProfileEffectId(profile, decodeEffect(fpte[1])); - } else { - updateProfileThemeColors(profile, primaryColor, decodeColor(fpte[1])); - updateProfileEffectId(profile, decodeEffect(fpte[2])); - } - - return profile; -} diff --git a/src/equicordplugins/homeTyping/index.tsx b/src/equicordplugins/homeTyping/index.tsx index 7331753e..d93e7c3e 100644 --- a/src/equicordplugins/homeTyping/index.tsx +++ b/src/equicordplugins/homeTyping/index.tsx @@ -6,9 +6,10 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findExportedComponentLazy, findStoreLazy } from "@webpack"; +import { findComponentByCodeLazy, findStoreLazy } from "@webpack"; import { useStateFromStores } from "@webpack/common"; -const ThreeDots = findExportedComponentLazy("Dots", "AnimatedDots"); + +const ThreeDots = findComponentByCodeLazy(".dots,", "dotRadius:"); const TypingStore = findStoreLazy("TypingStore"); diff --git a/src/equicordplugins/limitMiddleClickPaste/index.ts b/src/equicordplugins/limitMiddleClickPaste/index.ts index c39f4483..7fdbafd9 100644 --- a/src/equicordplugins/limitMiddleClickPaste/index.ts +++ b/src/equicordplugins/limitMiddleClickPaste/index.ts @@ -59,20 +59,20 @@ export default definePlugin({ // Discord adds it's paste listeners to #app-mount. We can intercept them // by attaching listeners a child element. containerEl = document.querySelector("[class^=appAsidePanelWrapper]")!; - containerEl.addEventListener("paste", blockPastePropogation); + containerEl?.addEventListener("paste", blockPastePropogation); // Also add them to body to intercept the event listeners on document - document.body.addEventListener("paste", blockPastePropogation); + document?.body?.addEventListener("paste", blockPastePropogation); - document.body.addEventListener("mousedown", disablePasteOnMousedown); + document?.body?.addEventListener("mousedown", disablePasteOnMousedown); }, stop() { - containerEl.removeEventListener("paste", blockPastePropogation); + containerEl?.removeEventListener("paste", blockPastePropogation); - document.body.removeEventListener("paste", blockPastePropogation); + document?.body?.removeEventListener("paste", blockPastePropogation); - document.body.removeEventListener("mousedown", disablePasteOnMousedown); + document?.body?.removeEventListener("mousedown", disablePasteOnMousedown); pasteDisabled = false; }, }); diff --git a/src/equicordplugins/pinIcon/index.tsx b/src/equicordplugins/pinIcon/index.tsx index c8e76f5f..ac547423 100644 --- a/src/equicordplugins/pinIcon/index.tsx +++ b/src/equicordplugins/pinIcon/index.tsx @@ -21,7 +21,7 @@ import definePlugin from "@utils/types"; import { Message } from "discord-types/general"; function PinIcon({ style = {} }) { - return ; + return ; } export default definePlugin({ name: "PinIcon", diff --git a/src/equicordplugins/unreadBadgeCount/index.tsx b/src/equicordplugins/unreadBadgeCount/index.tsx index e4df1516..4d7d8724 100644 --- a/src/equicordplugins/unreadBadgeCount/index.tsx +++ b/src/equicordplugins/unreadBadgeCount/index.tsx @@ -10,14 +10,37 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findStoreLazy } from "@webpack"; import { ReadStateStore, useStateFromStores } from "@webpack/common"; import { Channel } from "discord-types/general"; import { JSX } from "react"; const UserGuildSettingsStore = findStoreLazy("UserGuildSettingsStore"); const JoinedThreadsStore = findStoreLazy("JoinedThreadsStore"); -const { NumberBadge } = findByPropsLazy("NumberBadge"); + +function NumberBadge({ color, className, count }) { + return + + + {count} + + ; +} const settings = definePluginSettings({ showOnMutedChannels: {