Patched AlertModal, SweatDrops, TruncatedText, BackgroundImage components (#5913)

* Patched AlertModal, SweatDrops, TruncatedText
* Patch BackgroundImage component
* Inline PatchComponent calls
---------
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
QxxxGit
2025-06-11 03:32:36 -04:00
committed by GitHub
parent 155dbc370b
commit e95c1bbc76
6 changed files with 83 additions and 72 deletions

View File

@@ -1,6 +1,6 @@
import React from "react";
import { Button, Modal } from "react-bootstrap"; import { Button, Modal } from "react-bootstrap";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { PatchComponent } from "src/patch";
export interface IAlertModalProps { export interface IAlertModalProps {
text: JSX.Element | string; text: JSX.Element | string;
@@ -11,25 +11,28 @@ export interface IAlertModalProps {
onCancel: () => void; onCancel: () => void;
} }
export const AlertModal: React.FC<IAlertModalProps> = ({ export const AlertModal: React.FC<IAlertModalProps> = PatchComponent(
text, "AlertModal",
show, ({
confirmVariant = "danger", text,
confirmButtonText, show,
onConfirm, confirmVariant = "danger",
onCancel, confirmButtonText,
}) => { onConfirm,
return ( onCancel,
<Modal show={show}> }) => {
<Modal.Body>{text}</Modal.Body> return (
<Modal.Footer> <Modal show={show}>
<Button variant={confirmVariant} onClick={() => onConfirm()}> <Modal.Body>{text}</Modal.Body>
{confirmButtonText ?? <FormattedMessage id="actions.confirm" />} <Modal.Footer>
</Button> <Button variant={confirmVariant} onClick={() => onConfirm()}>
<Button variant="secondary" onClick={() => onCancel()}> {confirmButtonText ?? <FormattedMessage id="actions.confirm" />}
<FormattedMessage id="actions.cancel" /> </Button>
</Button> <Button variant="secondary" onClick={() => onCancel()}>
</Modal.Footer> <FormattedMessage id="actions.cancel" />
</Modal> </Button>
); </Modal.Footer>
}; </Modal>
);
}
);

View File

@@ -1,10 +1,11 @@
import React from "react"; import React from "react";
import { PatchComponent } from "src/patch";
export const BackgroundImage: React.FC<{ export const BackgroundImage: React.FC<{
imagePath: string | undefined; imagePath: string | undefined;
show: boolean; show: boolean;
alt?: string; alt?: string;
}> = ({ imagePath, show, alt }) => { }> = PatchComponent("BackgroundImage", ({ imagePath, show, alt }) => {
if (imagePath && show) { if (imagePath && show) {
const imageURL = new URL(imagePath); const imageURL = new URL(imagePath);
let isDefaultImage = imageURL.searchParams.get("default"); let isDefaultImage = imageURL.searchParams.get("default");
@@ -21,4 +22,4 @@ export const BackgroundImage: React.FC<{
} }
return null; return null;
}; });

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { PatchComponent } from "src/patch";
export const SweatDrops: React.FC = () => ( export const SweatDrops: React.FC = PatchComponent("SweatDrops", () => (
<span> <span>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -20,4 +21,4 @@ export const SweatDrops: React.FC = () => (
<rect x="0" y="0" width="36" height="36" fill="rgba(0, 0, 0, 0)" /> <rect x="0" y="0" width="36" height="36" fill="rgba(0, 0, 0, 0)" />
</svg> </svg>
</span> </span>
); ));

View File

@@ -3,6 +3,7 @@ import { Overlay, Tooltip } from "react-bootstrap";
import { Placement } from "react-bootstrap/Overlay"; import { Placement } from "react-bootstrap/Overlay";
import cx from "classnames"; import cx from "classnames";
import { useDebounce } from "src/hooks/debounce"; import { useDebounce } from "src/hooks/debounce";
import { PatchComponent } from "src/patch";
const CLASSNAME = "TruncatedText"; const CLASSNAME = "TruncatedText";
const CLASSNAME_TOOLTIP = `${CLASSNAME}-tooltip`; const CLASSNAME_TOOLTIP = `${CLASSNAME}-tooltip`;
@@ -15,57 +16,54 @@ interface ITruncatedTextProps {
className?: string; className?: string;
} }
export const TruncatedText: React.FC<ITruncatedTextProps> = ({ export const TruncatedText: React.FC<ITruncatedTextProps> = PatchComponent(
text, "TruncatedText",
className, ({ text, className, lineCount = 1, placement = "bottom", delay = 1000 }) => {
lineCount = 1, const [showTooltip, setShowTooltip] = useState(false);
placement = "bottom", const target = useRef(null);
delay = 1000,
}) => {
const [showTooltip, setShowTooltip] = useState(false);
const target = useRef(null);
const startShowingTooltip = useDebounce(() => setShowTooltip(true), delay); const startShowingTooltip = useDebounce(() => setShowTooltip(true), delay);
if (!text) return <></>; if (!text) return <></>;
const handleFocus = (element: HTMLElement) => { const handleFocus = (element: HTMLElement) => {
// Check if visible size is smaller than the content size // Check if visible size is smaller than the content size
if ( if (
element.offsetWidth < element.scrollWidth || element.offsetWidth < element.scrollWidth ||
element.offsetHeight + 10 < element.scrollHeight element.offsetHeight + 10 < element.scrollHeight
) )
startShowingTooltip(); startShowingTooltip();
}; };
const handleBlur = () => { const handleBlur = () => {
startShowingTooltip.cancel(); startShowingTooltip.cancel();
setShowTooltip(false); setShowTooltip(false);
}; };
const overlay = ( const overlay = (
<Overlay target={target.current} show={showTooltip} placement={placement}> <Overlay target={target.current} show={showTooltip} placement={placement}>
<Tooltip id={CLASSNAME} className={CLASSNAME_TOOLTIP}> <Tooltip id={CLASSNAME} className={CLASSNAME_TOOLTIP}>
{text}
</Tooltip>
</Overlay>
);
return (
<div
className={cx(CLASSNAME, className)}
style={{ WebkitLineClamp: lineCount }}
ref={target}
onMouseEnter={(e) => handleFocus(e.currentTarget)}
onFocus={(e) => handleFocus(e.currentTarget)}
onMouseLeave={handleBlur}
onBlur={handleBlur}
>
{text} {text}
</Tooltip> {overlay}
</Overlay> </div>
); );
}
return ( );
<div
className={cx(CLASSNAME, className)}
style={{ WebkitLineClamp: lineCount }}
ref={target}
onMouseEnter={(e) => handleFocus(e.currentTarget)}
onFocus={(e) => handleFocus(e.currentTarget)}
onMouseLeave={handleBlur}
onBlur={handleBlur}
>
{text}
{overlay}
</div>
);
};
export const TruncatedInlineText: React.FC<ITruncatedTextProps> = ({ export const TruncatedInlineText: React.FC<ITruncatedTextProps> = ({
text, text,

View File

@@ -143,7 +143,9 @@ Returns `void`.
#### Patchable components and functions #### Patchable components and functions
- `AlertModal`
- `App` - `App`
- `BackgroundImage`
- `BooleanSetting` - `BooleanSetting`
- `ChangeButtonSetting` - `ChangeButtonSetting`
- `CompressedPerformerDetailsPanel` - `CompressedPerformerDetailsPanel`
@@ -219,6 +221,7 @@ Returns `void`.
- `StudioIDSelect` - `StudioIDSelect`
- `StudioSelect` - `StudioSelect`
- `StudioSelect.sort` - `StudioSelect.sort`
- `SweatDrops`
- `TabTitleCounter` - `TabTitleCounter`
- `TagCard` - `TagCard`
- `TagCard.Details` - `TagCard.Details`
@@ -231,6 +234,7 @@ Returns `void`.
- `TagIDSelect` - `TagIDSelect`
- `TagSelect` - `TagSelect`
- `TagSelect.sort` - `TagSelect.sort`
- `TruncatedText`
- `PluginSettings` - `PluginSettings`
- `Setting` - `Setting`
- `SettingGroup` - `SettingGroup`

View File

@@ -727,6 +727,10 @@ declare namespace PluginApi {
"GalleryCard.Image": React.FC<any>; "GalleryCard.Image": React.FC<any>;
"GalleryCard.Overlays": React.FC<any>; "GalleryCard.Overlays": React.FC<any>;
"GalleryCard.Popovers": React.FC<any>; "GalleryCard.Popovers": React.FC<any>;
TruncatedText: React.FC<any>;
SweatDrops: React.FC<any>;
AlertModal: React.FC<any>;
BackgroundImage: React.FC<any>;
RatingNumber: React.FC<any>; RatingNumber: React.FC<any>;
RatingStars: React.FC<any>; RatingStars: React.FC<any>;
RatingSystem: React.FC<any>; RatingSystem: React.FC<any>;