Fix preview scrubber touch issues (#5267)

This commit is contained in:
WithoutPants
2024-09-16 16:30:16 +10:00
committed by GitHub
parent f543046349
commit e4ef14e830
4 changed files with 23 additions and 14 deletions

View File

@@ -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>
); );

View File

@@ -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}

View File

@@ -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 && (

View File

@@ -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;
} }