mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Fix preview scrubber touch issues (#5267)
This commit is contained in:
@@ -21,12 +21,12 @@ export const GalleryPreviewScrubber: React.FC<{
|
|||||||
const [activeIndex, setActiveIndex] = useState<number>();
|
const [activeIndex, setActiveIndex] = useState<number>();
|
||||||
const debounceSetActiveIndex = useThrottle(setActiveIndex, 50);
|
const debounceSetActiveIndex = useThrottle(setActiveIndex, 50);
|
||||||
|
|
||||||
function onScrubberClick() {
|
function onScrubberClick(index: number) {
|
||||||
if (activeIndex === undefined || !onClick) {
|
if (!onClick) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(activeIndex);
|
onClick(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -47,7 +47,7 @@ export const GalleryPreviewScrubber: React.FC<{
|
|||||||
totalSprites={imageCount}
|
totalSprites={imageCount}
|
||||||
activeIndex={activeIndex}
|
activeIndex={activeIndex}
|
||||||
setActiveIndex={(i) => debounceSetActiveIndex(i)}
|
setActiveIndex={(i) => debounceSetActiveIndex(i)}
|
||||||
onClick={() => onScrubberClick()}
|
onClick={onScrubberClick}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ function scaleToFit(dimensions: { w: number; h: number }, bounds: DOMRect) {
|
|||||||
return Math.min(rw, rh);
|
return Math.min(rw, rh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultSprites = 81; // 9x9 grid by default
|
||||||
|
|
||||||
export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
|
export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
|
||||||
vttPath,
|
vttPath,
|
||||||
onClick,
|
onClick,
|
||||||
@@ -83,15 +85,16 @@ export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
|
|||||||
return start;
|
return start;
|
||||||
}, [sprite]);
|
}, [sprite]);
|
||||||
|
|
||||||
function onScrubberClick() {
|
function onScrubberClick(index: number) {
|
||||||
if (!sprite || !onClick) {
|
if (!onClick || !spriteInfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(sprite.start);
|
const s = spriteInfo[index];
|
||||||
|
onClick(s.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spriteInfo && hasLoaded) return null;
|
if (spriteInfo === null) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="preview-scrubber">
|
<div className="preview-scrubber">
|
||||||
@@ -104,7 +107,7 @@ export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<HoverScrubber
|
<HoverScrubber
|
||||||
totalSprites={spriteInfo?.length ?? 0}
|
totalSprites={spriteInfo?.length ?? defaultSprites}
|
||||||
activeIndex={activeIndex}
|
activeIndex={activeIndex}
|
||||||
setActiveIndex={(i) => debounceSetActiveIndex(i)}
|
setActiveIndex={(i) => debounceSetActiveIndex(i)}
|
||||||
onClick={onScrubberClick}
|
onClick={onScrubberClick}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface IHoverScrubber {
|
|||||||
totalSprites: number;
|
totalSprites: number;
|
||||||
activeIndex: number | undefined;
|
activeIndex: number | undefined;
|
||||||
setActiveIndex: (index: number | undefined) => void;
|
setActiveIndex: (index: number | undefined) => void;
|
||||||
onClick?: () => void;
|
onClick?: (index: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HoverScrubber: React.FC<IHoverScrubber> = ({
|
export const HoverScrubber: React.FC<IHoverScrubber> = ({
|
||||||
@@ -82,7 +82,10 @@ export const HoverScrubber: React.FC<IHoverScrubber> = ({
|
|||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onClick();
|
|
||||||
|
const i = getActiveIndex(e);
|
||||||
|
if (i === undefined) return;
|
||||||
|
onClick(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
const indicatorStyle = useMemo(() => {
|
const indicatorStyle = useMemo(() => {
|
||||||
@@ -107,8 +110,8 @@ export const HoverScrubber: React.FC<IHoverScrubber> = ({
|
|||||||
onTouchMove={onMove}
|
onTouchMove={onMove}
|
||||||
onMouseLeave={onLeave}
|
onMouseLeave={onLeave}
|
||||||
onTouchEnd={onLeave}
|
onTouchEnd={onLeave}
|
||||||
|
onTouchCancel={onLeave}
|
||||||
onClick={onScrubberClick}
|
onClick={onScrubberClick}
|
||||||
onTouchStart={onScrubberClick}
|
|
||||||
/>
|
/>
|
||||||
<div className="hover-scrubber-indicator">
|
<div className="hover-scrubber-indicator">
|
||||||
{activeIndex !== undefined && (
|
{activeIndex !== undefined && (
|
||||||
|
|||||||
@@ -35,9 +35,12 @@ function getSpriteInfo(vttPath: string, response: string) {
|
|||||||
return sprites;
|
return sprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// useSpriteInfo is a hook that fetches a VTT file and parses it for sprite information.
|
||||||
|
// If the vttPath is undefined, the hook will return undefined.
|
||||||
|
// If the response is not ok, the hook will return null. This usually indicates missing sprite.
|
||||||
export function useSpriteInfo(vttPath: string | undefined) {
|
export function useSpriteInfo(vttPath: string | undefined) {
|
||||||
const [spriteInfo, setSpriteInfo] = useState<
|
const [spriteInfo, setSpriteInfo] = useState<
|
||||||
ISceneSpriteInfo[] | undefined
|
ISceneSpriteInfo[] | undefined | null
|
||||||
>();
|
>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -48,7 +51,7 @@ export function useSpriteInfo(vttPath: string | undefined) {
|
|||||||
|
|
||||||
fetch(vttPath).then((response) => {
|
fetch(vttPath).then((response) => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
setSpriteInfo(undefined);
|
setSpriteInfo(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user