diff --git a/src/components/ImageWithError.tsx b/src/components/ImageWithError.tsx index a5b91675e..3619b3786 100644 --- a/src/components/ImageWithError.tsx +++ b/src/components/ImageWithError.tsx @@ -4,6 +4,7 @@ import { createSignal, JSXElement, Show } from "solid-js" export const ImageWithError = ( props: ImageProps & { fallbackErr?: JSXElement + onLoad?: () => void }, ) => { const [err, setErr] = createSignal(false) @@ -11,6 +12,7 @@ export const ImageWithError = ( { setErr(true) }} diff --git a/src/pages/home/folder/GridItem.tsx b/src/pages/home/folder/GridItem.tsx index abaa550e8..aa0eb61b7 100644 --- a/src/pages/home/folder/GridItem.tsx +++ b/src/pages/home/folder/GridItem.tsx @@ -1,7 +1,7 @@ import { Center, VStack, Icon, Text } from "@hope-ui/solid" import { Motion } from "solid-motionone" import { useContextMenu } from "solid-contextmenu" -import { batch, Show } from "solid-js" +import { batch, Show, createSignal, onMount, onCleanup } from "solid-js" import { CenterLoading, LinkWithPush, ImageWithError } from "~/components" import { usePath, useRouter, useUtil } from "~/hooks" import { checkboxOpen, getMainColor, local, selectIndex } from "~/store" @@ -27,8 +27,37 @@ export const GridItem = (props: { obj: StoreObj; index: number }) => { const { pushHref, to } = useRouter() const { openWithDoubleClick, toggleWithClick, restoreSelectionCache } = useSelectWithMouse() + + const [isVisible, setIsVisible] = createSignal(false) + const [loaded, setLoaded] = createSignal(false) + const [canLoad, setCanLoad] = createSignal(false) + let ref: HTMLDivElement | undefined + let loadTimeout: number | undefined + + onMount(() => { + if (ref) { + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + loadTimeout = setTimeout(() => setCanLoad(true), 500) + } else { + if (loadTimeout) clearTimeout(loadTimeout) + setCanLoad(false) + } + setIsVisible(entry.isIntersecting) + }, + { rootMargin: "50px" }, + ) + observer.observe(ref) + onCleanup(() => { + observer.disconnect() + if (loadTimeout) clearTimeout(loadTimeout) + }) + } + }) return ( { }} /> - + { fallbackErr={objIcon} src={props.obj.thumb} loading="lazy" + onLoad={() => setLoaded(true)} />