From 683d1f8e64b9b337c53dcaa6e584e7e8a25cabf5 Mon Sep 17 00:00:00 2001
From: tarjelavik <Tarje.Lavik@ub.uib.no>
Date: Thu, 7 Oct 2021 13:47:32 +0200
Subject: [PATCH] Add react-intersection-observer for a more performant loading

---
 web/components/Sections/MiradorGallery.js | 38 +++++++++++++++-----
 web/components/Sections/SingleObject.js   | 42 +++++++++++++++++------
 web/package.json                          |  1 +
 web/yarn.lock                             |  5 +++
 4 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/web/components/Sections/MiradorGallery.js b/web/components/Sections/MiradorGallery.js
index f6efc28..0890933 100644
--- a/web/components/Sections/MiradorGallery.js
+++ b/web/components/Sections/MiradorGallery.js
@@ -1,7 +1,7 @@
 import dynamic from 'next/dynamic'
-import { Flex } from '@chakra-ui/react'
+import { useInView } from 'react-intersection-observer'
+import { Flex, Grid } from '@chakra-ui/react'
 import Caption from './shared/Caption'
-import WrapperGrid from './WrapperGrid'
 
 const MiradorWithNoSSR = dynamic(() => import('../MiradorViewer'), { ssr: false })
 
@@ -9,18 +9,38 @@ export default function MiradorGallery(props) {
   if ((!props && !props.items) || props.disabled === true) {
     return null
   }
-
   const { title, description, items } = props
 
+  const { ref, inView } = useInView({
+    root: null,
+    rootMargin: '0px',
+    triggerOnce: true,
+    threshold: 1.0,
+  })
+
+  const height = '60vh'
+
   return (
-    <WrapperGrid>
-      {items ? (
+    <Grid
+      ref={ref}
+      minH={height}
+      maxW={['xl', '4xl', '4xl', '6xl']}
+      my={{ base: '6', md: '16', lg: '16', xl: '20' }}
+      borderBottom={{ base: 'solid 1px', md: 'none' }}
+      borderColor="gray.200"
+      gridGap={[2, null, 5, null]}
+      gridTemplateAreas={{ base: '"image" "metadata"', xl: '"image metadata"' }}
+      gridTemplateColumns={{ base: 'auto', lg: '10fr 3fr' }}
+      gridTemplateRows="1fr auto"
+      mx="auto"
+      px={[4, 4, null, null]}
+    >
+      {items && inView && (
         <MiradorWithNoSSR gridArea="image" variant="standard" manifests={items} />
-      ) : (
-        <Flex gridArea="image">Mangler manifest</Flex>
       )}
+      {!items && <Flex gridArea="image">Mangler manifest</Flex>}
 
-      <Caption title={title} content={description} />
-    </WrapperGrid>
+      {inView && <Caption title={title} content={description} />}
+    </Grid>
   )
 }
diff --git a/web/components/Sections/SingleObject.js b/web/components/Sections/SingleObject.js
index 45c1474..76b428a 100644
--- a/web/components/Sections/SingleObject.js
+++ b/web/components/Sections/SingleObject.js
@@ -1,20 +1,41 @@
 import dynamic from 'next/dynamic'
-import { Flex } from '@chakra-ui/react'
+import { useInView } from 'react-intersection-observer'
+import { Flex, Grid } from '@chakra-ui/react'
 import Caption from './shared/Caption'
-import WrapperGrid from './WrapperGrid'
 
 const MiradorWithNoSSR = dynamic(() => import('../MiradorViewer'), { ssr: false })
 
-export default function SingleObject(props) {
+const SingleObject = (props) => {
   if ((!props && !props.item) || props.disabled === true) {
     return null
   }
-
   const { title, description, item, canvasUrl } = props
 
+  const { ref, inView } = useInView({
+    root: null,
+    rootMargin: '200px 0px',
+    triggerOnce: true,
+    threshold: 1.0,
+  })
+
+  const height = '60vh'
+
   return (
-    <WrapperGrid>
-      {item?.manifest ? (
+    <Grid
+      ref={ref}
+      minH={height}
+      maxW={['xl', '4xl', '4xl', '6xl']}
+      my={{ base: '6', md: '16', lg: '16', xl: '20' }}
+      borderBottom={{ base: 'solid 1px', md: 'none' }}
+      borderColor="gray.200"
+      gridGap={[2, null, 5, null]}
+      gridTemplateAreas={{ base: '"image" "metadata"', xl: '"image metadata"' }}
+      gridTemplateColumns={{ base: 'auto', lg: '10fr 3fr' }}
+      gridTemplateRows="1fr auto"
+      mx="auto"
+      px={[4, 4, null, null]}
+    >
+      {item.manifest && inView && (
         <MiradorWithNoSSR
           gridArea="image"
           variant="basic"
@@ -25,11 +46,12 @@ export default function SingleObject(props) {
             },
           ]}
         />
-      ) : (
-        <Flex gridArea="image">Mangler manifest</Flex>
       )}
+      {!item.manifest && <Flex gridArea="image">Mangler manifest</Flex>}
 
-      <Caption title={title} content={description} sourceItem={item} />
-    </WrapperGrid>
+      {inView && <Caption title={title} content={description} sourceItem={item} />}
+    </Grid>
   )
 }
+
+export default SingleObject
diff --git a/web/package.json b/web/package.json
index b9eb6d6..ef120df 100644
--- a/web/package.json
+++ b/web/package.json
@@ -40,6 +40,7 @@
     "react-icons": "^4.1.0",
     "react-inlinesvg": "^2.2.2",
     "react-instagram-embed": "^2.0.1",
+    "react-intersection-observer": "^8.32.1",
     "react-map-gl": "^5.2.9",
     "react-roman": "^2.0.0",
     "react-twitter-embed": "^3.0.3"
diff --git a/web/yarn.lock b/web/yarn.lock
index a246f93..1f57692 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -11770,6 +11770,11 @@ react-instagram-embed@^2.0.1:
   resolved "https://registry.yarnpkg.com/react-instagram-embed/-/react-instagram-embed-2.0.1.tgz#c1a21192ccbbbbd2e44510f21625479ba45164d5"
   integrity sha512-ScUFJPuTwAq0SgLEfW4VFu06H69A9EE/sa7GuCQsmVKEfq5tzdl0sLuksE+olVo7lVVHvZz0qAxJijBf44Z4Lg==
 
+react-intersection-observer@^8.32.1:
+  version "8.32.1"
+  resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-8.32.1.tgz#9b949871eb35eb1fc730732bbf8fcfaaaf3f5b02"
+  integrity sha512-FOmMkMw7MeJ8FkuADpU8TRcvGuTvPB+DRkaikS1QXcWArYLCWC3mjRorq2XeRGBuqmaueOBd27PUazTu9AgInw==
+
 react-is@17.0.2, "react-is@^16.8.0 || ^17.0.0", react-is@^17.0.2:
   version "17.0.2"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
-- 
GitLab