Skip to content

Commit

Permalink
Lazy load images (#4228)
Browse files Browse the repository at this point in the history
* Add lazy loading for many images
* Load sprites on first hover of scrubber
  • Loading branch information
WithoutPants committed Oct 23, 2023
1 parent 87bdbb2 commit 298f3d4
Show file tree
Hide file tree
Showing 18 changed files with 72 additions and 11 deletions.
2 changes: 2 additions & 0 deletions ui/v2.5/src/components/Galleries/GalleryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const GalleryCard: React.FC<IProps> = (props) => {
) : (
<img
className="image-thumbnail"
loading="lazy"
alt={props.gallery.studio.name}
src={props.gallery.studio.image_path ?? ""}
/>
Expand Down Expand Up @@ -153,6 +154,7 @@ export const GalleryCard: React.FC<IProps> = (props) => {
<>
{props.gallery.cover ? (
<img
loading="lazy"
className="gallery-card-image"
alt={props.gallery.title ?? ""}
src={`${props.gallery.cover.paths.thumbnail}`}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Galleries/GalleryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export const GalleryList: React.FC<IGalleryList> = ({
<Link to={`/galleries/${gallery.id}`}>
{gallery.cover ? (
<img
loading="lazy"
alt={gallery.title ?? ""}
className="w-100 w-sm-auto"
src={`${gallery.cover.paths.thumbnail}`}
Expand Down
2 changes: 1 addition & 1 deletion ui/v2.5/src/components/Galleries/GalleryWallCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const GalleryWallCard: React.FC<IProps> = ({ gallery }) => {
tabIndex={0}
>
<RatingSystem value={gallery.rating100 ?? undefined} disabled />
<img src={cover} alt="" className={CLASSNAME_IMG} />
<img loading="lazy" src={cover} alt="" className={CLASSNAME_IMG} />
<footer className={CLASSNAME_FOOTER}>
<Link
to={`/galleries/${gallery.id}`}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Movies/MovieCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export const MovieCard: React.FC<IProps> = (props: IProps) => {
image={
<>
<img
loading="lazy"
className="movie-card-image"
alt={props.movie.name ?? ""}
src={props.movie.front_image_path ?? ""}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Performers/PerformerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ export const PerformerCard: React.FC<IPerformerCardProps> = ({
image={
<>
<img
loading="lazy"
className="performer-card-image"
alt={performer.name ?? ""}
src={performer.image_path ?? ""}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Performers/PerformerListTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const PerformerListTable: React.FC<IPerformerListTableProps> = (
<td>
<Link to={`/performers/${performer.id}`}>
<img
loading="lazy"
className="image-thumbnail"
alt={performer.name ?? ""}
src={performer.image_path ?? ""}
Expand Down
30 changes: 25 additions & 5 deletions ui/v2.5/src/components/Scenes/PreviewScrubber.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React, { useRef, useMemo, useState, useLayoutEffect } from "react";
import React, {
useRef,
useMemo,
useState,
useLayoutEffect,
useEffect,
} from "react";
import { useSpriteInfo } from "src/hooks/sprite";
import { useThrottle } from "src/hooks/throttle";
import TextUtils from "src/utils/text";
import cx from "classnames";

interface IHoverScrubber {
totalSprites: number;
Expand Down Expand Up @@ -62,7 +69,11 @@ const HoverScrubber: React.FC<IHoverScrubber> = ({
}, [activeIndex, totalSprites]);

return (
<div className="hover-scrubber">
<div
className={cx("hover-scrubber", {
"hover-scrubber-inactive": !totalSprites,
})}
>
<div
className="hover-scrubber-area"
onMouseMove={onMouseMove}
Expand Down Expand Up @@ -109,7 +120,9 @@ export const PreviewScrubber: React.FC<IScenePreviewProps> = ({

const debounceSetActiveIndex = useThrottle(setActiveIndex, 50);

const spriteInfo = useSpriteInfo(vttPath);
// hold off on loading vtt until first mouse over
const [hasLoaded, setHasLoaded] = useState(false);
const spriteInfo = useSpriteInfo(hasLoaded ? vttPath : undefined);

const sprite = useMemo(() => {
if (!spriteInfo || activeIndex === undefined) {
Expand All @@ -118,6 +131,13 @@ export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
return spriteInfo[activeIndex];
}, [activeIndex, spriteInfo]);

// mark as loaded on the first hover
useEffect(() => {
if (activeIndex !== undefined) {
setHasLoaded(true);
}
}, [activeIndex]);

useLayoutEffect(() => {
const imageParent = imageParentRef.current;

Expand Down Expand Up @@ -153,7 +173,7 @@ export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
onClick(sprite.start);
}

if (!spriteInfo) return null;
if (!spriteInfo && hasLoaded) return null;

return (
<div className="preview-scrubber">
Expand All @@ -166,7 +186,7 @@ export const PreviewScrubber: React.FC<IScenePreviewProps> = ({
</div>
)}
<HoverScrubber
totalSprites={spriteInfo.length}
totalSprites={spriteInfo?.length ?? 0}
activeIndex={activeIndex}
setActiveIndex={(i) => debounceSetActiveIndex(i)}
onClick={onScrubberClick}
Expand Down
14 changes: 12 additions & 2 deletions ui/v2.5/src/components/Scenes/SceneCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ export const ScenePreview: React.FC<IScenePreviewProps> = ({

return (
<div className={cx("scene-card-preview", { portrait: isPortrait })}>
<img className="scene-card-preview-image" src={image} alt="" />
<img
className="scene-card-preview-image"
loading="lazy"
src={image}
alt=""
/>
<video
disableRemotePlayback
playsInline
Expand Down Expand Up @@ -166,7 +171,12 @@ export const SceneCard: React.FC<ISceneCardProps> = (
}

return (
<img className="image-thumbnail" alt={studioName} src={studioImage} />
<img
className="image-thumbnail"
loading="lazy"
alt={studioName}
src={studioImage}
/>
);
}

Expand Down
6 changes: 5 additions & 1 deletion ui/v2.5/src/components/Scenes/SceneDetails/QueueViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ export const QueueViewer: React.FC<IPlaylistViewer> = ({
>
<div className="ml-1 d-flex align-items-center">
<div className="thumbnail-container">
<img alt={scene.title ?? ""} src={scene.paths.screenshot ?? ""} />
<img
loading="lazy"
alt={scene.title ?? ""}
src={scene.paths.screenshot ?? ""}
/>
</div>
<div>
<span className="align-middle text-break">
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Scenes/SceneListTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const SceneListTable: React.FC<ISceneListTableProps> = (
<td>
<Link to={sceneLink}>
<img
loading="lazy"
className="image-thumbnail"
alt={title}
src={scene.paths.screenshot ?? ""}
Expand Down
10 changes: 10 additions & 0 deletions ui/v2.5/src/components/Scenes/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,16 @@ input[type="range"].blue-slider {
z-index: 1;
}

&.hover-scrubber-inactive {
.hover-scrubber-area {
cursor: inherit;
}

.hover-scrubber-indicator {
background-color: inherit;
}
}

.hover-scrubber-indicator {
background-color: rgba(255, 255, 255, 0.1);
bottom: -100%;
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Shared/GridCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const GridCard: React.FC<ICardProps> = (props: ICardProps) => {
if (props.interactiveHeatmap) {
return (
<img
loading="lazy"
src={props.interactiveHeatmap}
alt="interactive heatmap"
className="interactive-heatmap"
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Studios/StudioCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export const StudioCard: React.FC<IProps> = ({
linkClassName="studio-card-header"
image={
<img
loading="lazy"
className="studio-card-image"
alt={studio.name}
src={studio.image_path ?? ""}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Tagger/scenes/TaggerScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const TaggerSceneDetails: React.FC<ITaggerSceneDetails> = ({ scene }) => {
className="performer-tag col m-auto zoom-2"
>
<img
loading="lazy"
className="image-thumbnail"
alt={performer.name ?? ""}
src={performer.image_path ?? ""}
Expand Down
7 changes: 6 additions & 1 deletion ui/v2.5/src/components/Tagger/studios/StashSearchResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,12 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
key={p.remote_site_id}
onClick={() => setModalStudio(p)}
>
<img src={(p.image ?? [])[0]} alt="" className="StudioTagger-thumb" />
<img
loading="lazy"
src={(p.image ?? [])[0]}
alt=""
className="StudioTagger-thumb"
/>
<span>{p.name}</span>
</Button>
));
Expand Down
2 changes: 1 addition & 1 deletion ui/v2.5/src/components/Tagger/studios/StudioTagger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ const StudioTaggerList: React.FC<IStudioTaggerListProps> = ({
<div></div>
<div>
<Card className="studio-card">
<img src={studio.image_path ?? ""} alt="" />
<img loading="lazy" src={studio.image_path ?? ""} alt="" />
</Card>
</div>
<div className={`${CLASSNAME}-details-text`}>
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Tags/TagCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export const TagCard: React.FC<IProps> = ({
linkClassName="tag-card-header"
image={
<img
loading="lazy"
className="tag-card-image"
alt={tag.name}
src={tag.image_path ?? ""}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Wall/WallItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const Preview: React.FC<{

const image = (
<img
loading="lazy"
alt=""
className="wall-item-media"
src={
Expand Down

0 comments on commit 298f3d4

Please sign in to comment.