mirror of
https://github.com/System-End/Vencord.git
synced 2026-04-19 19:45:09 +00:00
fix & future proof tooltips
This commit is contained in:
parent
58ef6585af
commit
c123efd659
10 changed files with 88 additions and 32 deletions
26
packages/discord-types/src/components.d.ts
vendored
26
packages/discord-types/src/components.d.ts
vendored
|
|
@ -35,17 +35,19 @@ export type Button = ComponentType<ButtonProps> & {
|
|||
|
||||
// #endregion
|
||||
|
||||
export type Tooltip = ComponentType<{
|
||||
export interface TooltipChildrenProps {
|
||||
onClick(): void;
|
||||
onMouseEnter(): void;
|
||||
onMouseLeave(): void;
|
||||
onContextMenu(): void;
|
||||
onFocus(): void;
|
||||
onBlur(): void;
|
||||
"aria-label"?: string;
|
||||
}
|
||||
|
||||
export interface TooltipProps {
|
||||
text: ReactNode | ComponentType;
|
||||
children: FunctionComponent<{
|
||||
onClick(): void;
|
||||
onMouseEnter(): void;
|
||||
onMouseLeave(): void;
|
||||
onContextMenu(): void;
|
||||
onFocus(): void;
|
||||
onBlur(): void;
|
||||
"aria-label"?: string;
|
||||
}>;
|
||||
children: FunctionComponent<TooltipChildrenProps>;
|
||||
"aria-label"?: string;
|
||||
|
||||
allowOverflow?: boolean;
|
||||
|
|
@ -62,7 +64,9 @@ export type Tooltip = ComponentType<{
|
|||
|
||||
tooltipClassName?: string;
|
||||
tooltipContentClassName?: string;
|
||||
}> & {
|
||||
}
|
||||
|
||||
export type Tooltip = ComponentType<TooltipProps> & {
|
||||
Colors: Record<"BLACK" | "BRAND" | "CUSTOM" | "GREEN" | "GREY" | "PRIMARY" | "RED" | "YELLOW", string>;
|
||||
};
|
||||
|
||||
|
|
|
|||
20
src/components/TooltipContainer.tsx
Normal file
20
src/components/TooltipContainer.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { TooltipProps } from "@vencord/discord-types";
|
||||
import { Tooltip } from "@webpack/common";
|
||||
|
||||
export function TooltipContainer({ children, ...props }: Omit<TooltipProps, "children"> & { children: React.ReactNode; }) {
|
||||
return (
|
||||
<Tooltip {...props}>
|
||||
{tooltipProps =>
|
||||
<div {...tooltipProps}>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
29
src/components/TooltipFallback.tsx
Normal file
29
src/components/TooltipFallback.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2025 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Tooltip } from "@vencord/discord-types";
|
||||
|
||||
const NOOP = () => { };
|
||||
|
||||
/** Don't use this */
|
||||
export const TooltipFallback: Tooltip = ({ children }) => {
|
||||
if (typeof children !== "function") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const node = children({
|
||||
onBlur: NOOP,
|
||||
onFocus: NOOP,
|
||||
onMouseEnter: NOOP,
|
||||
onMouseLeave: NOOP,
|
||||
onClick: NOOP,
|
||||
onContextMenu: NOOP
|
||||
});
|
||||
|
||||
return <>{node}</>;
|
||||
};
|
||||
|
||||
TooltipFallback.Colors = {} as any;
|
||||
|
|
@ -5,12 +5,13 @@
|
|||
*/
|
||||
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { TooltipContainer } from "@components/TooltipContainer";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { classes } from "@utils/misc";
|
||||
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { TabBar, Text, Timestamp, TooltipContainer, useState } from "@webpack/common";
|
||||
import { TabBar, Text, Timestamp, useState } from "@webpack/common";
|
||||
|
||||
import { parseEditContent } from ".";
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co
|
|||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { SafetyIcon } from "@components/Icons";
|
||||
import { TooltipContainer } from "@components/TooltipContainer";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classes } from "@utils/misc";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import type { Guild, GuildMember } from "@vencord/discord-types";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { Button, ChannelStore, Dialog, GuildMemberStore, GuildRoleStore, GuildStore, match, Menu, PermissionsBits, Popout, TooltipContainer, useRef, UserStore } from "@webpack/common";
|
||||
import { Button, ChannelStore, Dialog, GuildMemberStore, GuildRoleStore, GuildStore, match, Menu, PermissionsBits, Popout, useRef, UserStore } from "@webpack/common";
|
||||
|
||||
import openRolesAndUsersPermissionsModal, { PermissionType, RoleOrUserPermission } from "./components/RolesAndUsersPermissions";
|
||||
import UserPermissions from "./components/UserPermissions";
|
||||
|
|
|
|||
|
|
@ -21,12 +21,13 @@ import "./style.css";
|
|||
import { NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { NotesIcon, OpenExternalIcon } from "@components/Icons";
|
||||
import { TooltipContainer } from "@components/TooltipContainer";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classes } from "@utils/misc";
|
||||
import definePlugin from "@utils/types";
|
||||
import { Guild, User } from "@vencord/discord-types";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import { Alerts, Clickable, Menu, Parser, TooltipContainer } from "@webpack/common";
|
||||
import { Alerts, Clickable, Menu, Parser } from "@webpack/common";
|
||||
|
||||
import { Auth, initAuth, updateAuth } from "./auth";
|
||||
import { openReviewsModal } from "./components/ReviewModal";
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@ import "./styles.css";
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { TooltipContainer } from "@components/TooltipContainer";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { getIntlMessage } from "@utils/discord";
|
||||
import { canonicalizeMatch } from "@utils/patches";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Message } from "@vencord/discord-types";
|
||||
import { findComponentLazy } from "@webpack";
|
||||
import { ChannelStore, GuildMemberStore, Text, TooltipContainer } from "@webpack/common";
|
||||
import { ChannelStore, GuildMemberStore, Text } from "@webpack/common";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
const countDownFilter = canonicalizeMatch(/#{intl::MAX_AGE_NEVER}/);
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@ import "./styles.css";
|
|||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { TooltipContainer } from "@components/TooltipContainer";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { classNameFactory } from "@utils/css";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { User } from "@vencord/discord-types";
|
||||
import { DateUtils, RelationshipStore, Text, TooltipContainer } from "@webpack/common";
|
||||
import { DateUtils, RelationshipStore, Text } from "@webpack/common";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
const formatter = new Intl.DateTimeFormat(undefined, {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import { Divider } from "@components/Divider";
|
|||
import { FormSwitchCompat } from "@components/FormSwitch";
|
||||
import { Heading } from "@components/Heading";
|
||||
import { Paragraph } from "@components/Paragraph";
|
||||
import { TooltipContainer as TooltipContainerComponent } from "@components/TooltipContainer";
|
||||
import { TooltipFallback } from "@components/TooltipFallback";
|
||||
import { LazyComponent } from "@utils/lazyReact";
|
||||
import * as t from "@vencord/discord-types";
|
||||
import { filters, mapMangledModuleLazy, waitFor } from "@webpack";
|
||||
|
|
@ -52,17 +54,9 @@ export const Switch = FormSwitchCompat as never;
|
|||
export const Card = waitForComponent<never>("Card", filters.componentByCode(".editable),", ".outline:"));
|
||||
export const Checkbox = waitForComponent<t.Checkbox>("Checkbox", filters.componentByCode(".checkboxWrapperDisabled:"));
|
||||
|
||||
const Tooltips = mapMangledModuleLazy(".tooltipTop,bottom:", {
|
||||
Tooltip: filters.componentByCode("this.renderTooltip()]"),
|
||||
TooltipContainer: filters.componentByCode('="div"')
|
||||
}) as {
|
||||
Tooltip: t.Tooltip,
|
||||
TooltipContainer: t.TooltipContainer;
|
||||
};
|
||||
|
||||
// TODO: if these finds break, they should just return their children
|
||||
export const Tooltip = LazyComponent(() => Tooltips.Tooltip);
|
||||
export const TooltipContainer = LazyComponent(() => Tooltips.TooltipContainer);
|
||||
export const Tooltip = waitForComponent<t.Tooltip>("Tooltip", m => m.prototype?.shouldShowTooltip && m.prototype.render, TooltipFallback);
|
||||
/** @deprecated import from @vencord/components */
|
||||
export const TooltipContainer = TooltipContainerComponent as never;
|
||||
|
||||
export const TextInput = waitForComponent<t.TextInput>("TextInput", filters.componentByCode("#{intl::MAXIMUM_LENGTH_ERROR}", '"input"'));
|
||||
export const TextArea = waitForComponent<t.TextArea>("TextArea", filters.componentByCode("this.getPaddingRight()},id:"));
|
||||
|
|
|
|||
|
|
@ -19,22 +19,26 @@
|
|||
import { Logger } from "@utils/Logger";
|
||||
import { LazyComponent, LazyComponentWrapper } from "@utils/react";
|
||||
import { FilterFn, filters, lazyWebpackSearchHistory, waitFor } from "@webpack";
|
||||
import { ComponentType } from "react";
|
||||
|
||||
const logger = new Logger("Webpack");
|
||||
|
||||
export function waitForComponent<T extends React.ComponentType<any> = React.ComponentType<any> & Record<string, any>>(name: string, filter: FilterFn | string | string[]) {
|
||||
export function waitForComponent<T extends ComponentType<any> = ComponentType<any> & Record<string, any>>(name: string, filter: FilterFn | string | string[], fallbackValue: ComponentType<any> | null = null) {
|
||||
if (IS_REPORTER) lazyWebpackSearchHistory.push(["waitForComponent", Array.isArray(filter) ? filter : [filter]]);
|
||||
|
||||
let myValue: T = function () {
|
||||
let myValue: T | null = null;
|
||||
|
||||
const lazyComponent = LazyComponent(() => {
|
||||
if (myValue) return myValue;
|
||||
|
||||
const error = new Error(`Vencord could not find the ${name} Component`);
|
||||
logger.error(error);
|
||||
|
||||
if (IS_DEV) throw error;
|
||||
|
||||
return null;
|
||||
} as any;
|
||||
return fallbackValue!;
|
||||
}) as LazyComponentWrapper<T>;
|
||||
|
||||
const lazyComponent = LazyComponent(() => myValue) as LazyComponentWrapper<T>;
|
||||
waitFor(filter, (v: any) => {
|
||||
myValue = v;
|
||||
Object.assign(lazyComponent, v);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue