mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
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:
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
});
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
));
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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`
|
||||||
|
|||||||
4
ui/v2.5/src/pluginApi.d.ts
vendored
4
ui/v2.5/src/pluginApi.d.ts
vendored
@@ -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>;
|
||||||
|
|||||||
Reference in New Issue
Block a user