Improve component finding api and migrate plugins to use them
This commit is contained in:
parent
371b5b0be8
commit
ffe6512693
14 changed files with 89 additions and 57 deletions
|
@ -24,9 +24,9 @@ import { proxyLazy } from "@utils/lazy";
|
|||
import { Margins } from "@utils/margins";
|
||||
import { classes, isObjectEmpty } from "@utils/misc";
|
||||
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import { OptionType, Plugin } from "@utils/types";
|
||||
import { findByCode, findByPropsLazy } from "@webpack";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common";
|
||||
import { User } from "discord-types/general";
|
||||
import { Constructor } from "type-fest";
|
||||
|
@ -42,7 +42,7 @@ import {
|
|||
} from "./components";
|
||||
import { openContributorModal } from "./ContributorModal";
|
||||
|
||||
const UserSummaryItem = LazyComponent(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"));
|
||||
const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers");
|
||||
const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
|
||||
const UserRecord: Constructor<Partial<User>> = proxyLazy(() => UserStore.getCurrentUser().constructor) as any;
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
*/
|
||||
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { find, findByPropsLazy, findStoreLazy } from "@webpack";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import { findByPropsLazy, findStoreLazy } from "@webpack";
|
||||
import { useStateFromStores } from "@webpack/common";
|
||||
import type { CSSProperties } from "react";
|
||||
|
||||
|
@ -26,7 +26,7 @@ import { ExpandedGuildFolderStore, settings } from ".";
|
|||
|
||||
const ChannelRTCStore = findStoreLazy("ChannelRTCStore");
|
||||
const Animations = findByPropsLazy("a", "animated", "useTransition");
|
||||
const GuildsBar = LazyComponent(() => find(m => m.type?.toString().includes('("guildsnav")')));
|
||||
const GuildsBar = findComponentByCodeLazy('("guildsnav")');
|
||||
|
||||
export default ErrorBoundary.wrap(guildsBarProps => {
|
||||
const expandedFolders = useStateFromStores([ExpandedGuildFolderStore], () => ExpandedGuildFolderStore.getExpandedFolders());
|
||||
|
|
|
@ -11,12 +11,11 @@ import { Devs } from "@utils/constants";
|
|||
import { getTheme, Theme } from "@utils/discord";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import definePlugin, { OptionType, StartAt } from "@utils/types";
|
||||
import { findByCode } from "@webpack";
|
||||
import { Button, Forms } from "@webpack/common";
|
||||
|
||||
const ColorPicker = LazyComponent(() => findByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR"));
|
||||
const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR");
|
||||
|
||||
const colorPresets = [
|
||||
"#1E1514", "#172019", "#13171B", "#1C1C28", "#402D2D",
|
||||
|
|
|
@ -20,12 +20,12 @@ import { definePluginSettings, Settings } from "@api/Settings";
|
|||
import { Link } from "@components/Link";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { isTruthy } from "@utils/guards";
|
||||
import { useAwaiter } from "@utils/react";
|
||||
import { findComponentByCodeLazy, useAwaiter } from "@utils/react";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findByCodeLazy, findByPropsLazy } from "@webpack";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { ApplicationAssetUtils, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common";
|
||||
|
||||
const ActivityComponent = findByCodeLazy("onOpenGameProfile");
|
||||
const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile");
|
||||
const ActivityClassName = findByPropsLazy("activity", "buttonColor");
|
||||
const Colors = findByPropsLazy("profileColors");
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findByCodeLazy } from "@webpack";
|
||||
import { StatusSettingsStores } from "@webpack/common";
|
||||
|
||||
import style from "./style.css?managed";
|
||||
|
||||
const Button = findByCodeLazy("Button.Sizes.NONE,disabled:");
|
||||
const Button = findComponentByCodeLazy("Button.Sizes.NONE,disabled:");
|
||||
|
||||
function makeIcon(showCurrentGame?: boolean) {
|
||||
return function () {
|
||||
|
|
|
@ -22,9 +22,9 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
|||
import { Devs } from "@utils/constants.js";
|
||||
import { classes } from "@utils/misc";
|
||||
import { Queue } from "@utils/Queue";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { find, findByCode, findByPropsLazy } from "@webpack";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import {
|
||||
Button,
|
||||
ChannelStore,
|
||||
|
@ -45,9 +45,9 @@ const messageCache = new Map<string, {
|
|||
fetched: boolean;
|
||||
}>();
|
||||
|
||||
const Embed = LazyComponent(() => findByCode(".inlineMediaEmbed"));
|
||||
const AutoModEmbed = LazyComponent(() => findByCode(".withFooter]:", "childrenMessageContent:"));
|
||||
const ChannelMessage = LazyComponent(() => find(m => m.type?.toString()?.includes("renderSimpleAccessories)")));
|
||||
const Embed = findComponentByCodeLazy(".inlineMediaEmbed");
|
||||
const AutoModEmbed = findComponentByCodeLazy(".withFooter]:", "childrenMessageContent:");
|
||||
const ChannelMessage = findComponentByCodeLazy("renderSimpleAccessories)");
|
||||
|
||||
const SearchResultClasses = findByPropsLazy("message", "searchResult");
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ import { classNameFactory } from "@api/Styles";
|
|||
import { openImageModal, openUserProfile } from "@utils/discord";
|
||||
import { classes } from "@utils/misc";
|
||||
import { ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { LazyComponent, useAwaiter } from "@utils/react";
|
||||
import { findByProps, findByPropsLazy } from "@webpack";
|
||||
import { findExportedComponentLazy, useAwaiter } from "@utils/react";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { FluxDispatcher, Forms, GuildChannelStore, GuildMemberStore, moment, Parser, PresenceStore, RelationshipStore, ScrollerThin, SnowflakeUtils, TabBar, Timestamp, useEffect, UserStore, UserUtils, useState, useStateFromStores } from "@webpack/common";
|
||||
import { Guild, User } from "discord-types/general";
|
||||
|
||||
const IconUtils = findByPropsLazy("getGuildBannerURL");
|
||||
const IconClasses = findByPropsLazy("icon", "acronym", "childWrapper");
|
||||
const FriendRow = LazyComponent(() => findByProps("FriendRow").FriendRow);
|
||||
const FriendRow = findExportedComponentLazy("FriendRow");
|
||||
|
||||
const cl = classNameFactory("vc-gp-");
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { findByCode, findLazy } from "@webpack";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import { findLazy } from "@webpack";
|
||||
import { i18n, useToken } from "@webpack/common";
|
||||
|
||||
const ColorMap = findLazy(m => m.colors?.INTERACTIVE_MUTED?.css);
|
||||
const VerifiedIconComponent = LazyComponent(() => findByCode(".CONNECTIONS_ROLE_OFFICIAL_ICON_TOOLTIP"));
|
||||
const VerifiedIconComponent = findComponentByCodeLazy(".CONNECTIONS_ROLE_OFFICIAL_ICON_TOOLTIP");
|
||||
|
||||
export function VerifiedIcon() {
|
||||
const color = useToken(ColorMap.colors.INTERACTIVE_MUTED).hex();
|
||||
|
|
|
@ -24,15 +24,15 @@ import { Flex } from "@components/Flex";
|
|||
import { CopyIcon, LinkIcon } from "@components/Icons";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { copyWithToast } from "@utils/misc";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { findComponentByCodeLazy } from "@utils/react";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findByCode, findByCodeLazy, findByPropsLazy, findStoreLazy } from "@webpack";
|
||||
import { findByCodeLazy, findByPropsLazy, findStoreLazy } from "@webpack";
|
||||
import { Text, Tooltip, UserProfileStore } from "@webpack/common";
|
||||
import { User } from "discord-types/general";
|
||||
|
||||
import { VerifiedIcon } from "./VerifiedIcon";
|
||||
|
||||
const Section = LazyComponent(() => findByCode(".lastSection]:"));
|
||||
const Section = findComponentByCodeLazy(".lastSection]: ");
|
||||
const ThemeStore = findStoreLazy("ThemeStore");
|
||||
const platforms: { get(type: string): ConnectionPlatform; } = findByPropsLazy("isSupported", "getByUrl");
|
||||
const getTheme: (user: User, displayProfile: any) => any = findByCodeLazy(',"--profile-gradient-primary-color"');
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
|
||||
import { Settings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { LazyComponent } from "@utils/react";
|
||||
import { findComponentByCodeLazy, findComponentLazy } from "@utils/react";
|
||||
import { formatDuration } from "@utils/text";
|
||||
import { find, findByCode, findByPropsLazy } from "@webpack";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, moment, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common";
|
||||
import type { Channel } from "discord-types/general";
|
||||
|
||||
|
@ -81,14 +81,14 @@ const enum ChannelFlags {
|
|||
|
||||
const ChatScrollClasses = findByPropsLazy("auto", "content", "scrollerBase");
|
||||
const ChatClasses = findByPropsLazy("chat", "content", "noChat", "chatContent");
|
||||
const ChannelBeginHeader = LazyComponent(() => findByCode(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE"));
|
||||
const TagComponent = LazyComponent(() => find(m => {
|
||||
const ChannelBeginHeader = findComponentByCodeLazy(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE");
|
||||
const TagComponent = findComponentLazy(m => {
|
||||
if (typeof m !== "function") return false;
|
||||
|
||||
const code = Function.prototype.toString.call(m);
|
||||
// Get the component which doesn't include increasedActivity
|
||||
return code.includes(".Messages.FORUM_TAG_A11Y_FILTER_BY_TAG") && !code.includes("increasedActivityPill");
|
||||
}));
|
||||
});
|
||||
|
||||
const EmojiParser = findByPropsLazy("convertSurrogateToName");
|
||||
const EmojiUtils = findByPropsLazy("getURL", "buildEmojiReactionColorsPlatformed");
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { LazyComponent, useTimer } from "@utils/react";
|
||||
import { find } from "@webpack";
|
||||
import { findComponentByCodeLazy, useTimer } from "@utils/react";
|
||||
|
||||
import { cl } from "./utils";
|
||||
|
||||
|
@ -25,7 +24,7 @@ interface VoiceMessageProps {
|
|||
src: string;
|
||||
waveform: string;
|
||||
}
|
||||
const VoiceMessage = LazyComponent<VoiceMessageProps>(() => find(m => m.type?.toString().includes("waveform:")));
|
||||
const VoiceMessage = findComponentByCodeLazy<VoiceMessageProps>("waveform:");
|
||||
|
||||
export type VoicePreviewOptions = {
|
||||
src?: string;
|
||||
|
|
|
@ -20,14 +20,14 @@ import ErrorBoundary from "@components/ErrorBoundary";
|
|||
import { Devs } from "@utils/constants";
|
||||
import { sleep } from "@utils/misc";
|
||||
import { Queue } from "@utils/Queue";
|
||||
import { LazyComponent, useForceUpdater } from "@utils/react";
|
||||
import { findComponentByCodeLazy, useForceUpdater } from "@utils/react";
|
||||
import definePlugin from "@utils/types";
|
||||
import { findByCode, findByPropsLazy } from "@webpack";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { ChannelStore, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common";
|
||||
import { CustomEmoji } from "@webpack/types";
|
||||
import { Message, ReactionEmoji, User } from "discord-types/general";
|
||||
|
||||
const UserSummaryItem = LazyComponent(() => findByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"));
|
||||
const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers");
|
||||
const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar");
|
||||
|
||||
const queue = new Queue();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { FilterFn, filters, find, findByProps } from "@webpack";
|
||||
import { React, useEffect, useMemo, useReducer, useState } from "@webpack/common";
|
||||
|
||||
import { makeLazy } from "./lazy";
|
||||
|
@ -77,7 +78,6 @@ interface AwaiterOpts<T> {
|
|||
* @param fallbackValue The fallback value that will be used until the promise resolved
|
||||
* @returns [value, error, isPending]
|
||||
*/
|
||||
|
||||
export function useAwaiter<T>(factory: () => Promise<T>): AwaiterRes<T | null>;
|
||||
export function useAwaiter<T>(factory: () => Promise<T>, providedOpts: AwaiterOpts<T>): AwaiterRes<T>;
|
||||
export function useAwaiter<T>(factory: () => Promise<T>, providedOpts?: AwaiterOpts<T | null>): AwaiterRes<T | null> {
|
||||
|
@ -113,31 +113,16 @@ export function useAwaiter<T>(factory: () => Promise<T>, providedOpts?: AwaiterO
|
|||
|
||||
return [state.value, state.error, state.pending];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that can be used to force rerender react components
|
||||
*/
|
||||
|
||||
export function useForceUpdater(): () => void;
|
||||
export function useForceUpdater(withDep: true): [unknown, () => void];
|
||||
export function useForceUpdater(withDep?: true) {
|
||||
const r = useReducer(x => x + 1, 0);
|
||||
return withDep ? r : r[1];
|
||||
}
|
||||
/**
|
||||
* A lazy component. The factory method is called on first render. For example useful
|
||||
* for const Component = LazyComponent(() => findByDisplayName("...").default)
|
||||
* @param factory Function returning a Component
|
||||
* @param attempts How many times to try to get the component before giving up
|
||||
* @returns Result of factory function
|
||||
*/
|
||||
|
||||
export function LazyComponent<T extends object = any>(factory: () => React.ComponentType<T>, attempts = 5) {
|
||||
const get = makeLazy(factory, attempts);
|
||||
return (props: T) => {
|
||||
const Component = get() ?? NoopComponent;
|
||||
return <Component {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
interface TimerOpts {
|
||||
interval?: number;
|
||||
|
@ -159,3 +144,52 @@ export function useTimer({ interval = 1000, deps = [] }: TimerOpts) {
|
|||
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the component which includes all the given code. Checks for plain components, memos and forwardRefs
|
||||
*/
|
||||
export function findComponentByCode(...code: string[]) {
|
||||
const filter = filters.byCode(...code);
|
||||
return find(m => {
|
||||
if (filter(m)) return true;
|
||||
if (!m.$$typeof) return false;
|
||||
if (m.type) return filter(m.type); // memos
|
||||
if (m.render) return filter(m.render); // forwardRefs
|
||||
return false;
|
||||
}) ?? NoopComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first component that matches the filter, lazily.
|
||||
*/
|
||||
export function findComponentLazy<T extends object = any>(filter: FilterFn) {
|
||||
return LazyComponent<T>(() => find(filter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first component that includes all the given code, lazily
|
||||
*/
|
||||
export function findComponentByCodeLazy<T extends object = any>(...code: string[]) {
|
||||
return LazyComponent<T>(() => findComponentByCode(...code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first component that is exported by the first prop name, lazily
|
||||
*/
|
||||
export function findExportedComponentLazy<T extends object = any>(...props: string[]) {
|
||||
return LazyComponent<T>(() => findByProps(...props)?.[props[0]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A lazy component. The factory method is called on first render.
|
||||
* @param factory Function returning a Component
|
||||
* @param attempts How many times to try to get the component before giving up
|
||||
* @returns Result of factory function
|
||||
*/
|
||||
export function LazyComponent<T extends object = any>(factory: () => React.ComponentType<T>, attempts = 5) {
|
||||
const get = makeLazy(factory, attempts);
|
||||
return (props: T) => {
|
||||
const Component = get() ?? NoopComponent;
|
||||
return <Component {...props} />;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -386,7 +386,7 @@ export function findStore(name: string) {
|
|||
}
|
||||
|
||||
/**
|
||||
* findByDisplayName but lazy
|
||||
* findStore but lazy
|
||||
*/
|
||||
export function findStoreLazy(name: string) {
|
||||
return proxyLazy(() => findStore(name));
|
||||
|
|
Loading…
Reference in a new issue