a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

don't render offscreen leaflets on home

+40 -19
+2 -1
app/home/LeafletList.tsx
··· 48 48 return ( 49 49 <div className="homeLeafletGrid grow w-full h-full overflow-y-scroll no-scrollbar "> 50 50 <div className="grid auto-rows-max md:grid-cols-4 sm:grid-cols-3 grid-cols-2 gap-y-6 gap-x-4 sm:gap-6 grow pt-3 pb-28 sm:pt-6 sm:pb-12 sm:pl-6 sm:pr-1"> 51 - {leaflets.map((leaflet) => ( 51 + {leaflets.map((leaflet, index) => ( 52 52 <ReplicacheProvider 53 53 initialFactsOnly={!!identity} 54 54 key={leaflet.id} ··· 58 58 initialFacts={initialFacts?.[leaflet.root_entity] || []} 59 59 > 60 60 <LeafletPreview 61 + index={index} 61 62 token={leaflet} 62 63 leaflet_id={leaflet.root_entity} 63 64 loggedIn={!!identity}
+38 -18
app/home/LeafletPreview.tsx
··· 4 4 ThemeBackgroundProvider, 5 5 ThemeProvider, 6 6 } from "components/ThemeManager/ThemeProvider"; 7 - import { useRef, useState } from "react"; 7 + import { useEffect, useRef, useState } from "react"; 8 8 import { Link } from "react-aria-components"; 9 9 import { useBlocks } from "src/hooks/queries/useBlocks"; 10 10 import { ··· 26 26 import styles from "./LeafletPreview.module.css"; 27 27 28 28 export const LeafletPreview = (props: { 29 + index: number; 29 30 token: PermissionToken; 30 31 leaflet_id: string; 31 32 loggedIn: boolean; ··· 59 60 "rgba(var(--bg-page), var(--bg-page-alpha))", 60 61 }} 61 62 > 62 - <LeafletContent entityID={page} /> 63 + <LeafletContent entityID={page} index={props.index} /> 63 64 </div> 64 65 </div> 65 66 </ThemeBackgroundProvider> ··· 81 82 ); 82 83 }; 83 84 84 - const LeafletContent = (props: { entityID: string }) => { 85 + const LeafletContent = (props: { entityID: string; index: number }) => { 85 86 let type = useEntity(props.entityID, "page/type")?.data.value || "doc"; 86 87 let blocks = useBlocks(props.entityID); 87 88 let previewRef = useRef<HTMLDivElement | null>(null); 89 + let [isVisible, setIsVisible] = useState(props.index > 16 ? false : true); 90 + useEffect(() => { 91 + if (!previewRef.current) return; 92 + let observer = new IntersectionObserver( 93 + (entries) => { 94 + entries.forEach((entry) => { 95 + if (entry.isIntersecting) { 96 + setIsVisible(true); 97 + } else { 98 + setIsVisible(false); 99 + } 100 + }); 101 + }, 102 + { threshold: 0.1, root: null }, 103 + ); 104 + observer.observe(previewRef.current); 105 + return () => observer.disconnect(); 106 + }, [previewRef]); 88 107 89 108 if (type === "canvas") 90 109 return ( ··· 98 117 height: "calc(1272px * 2)", 99 118 }} 100 119 > 101 - <CanvasContent entityID={props.entityID} preview /> 120 + {isVisible && <CanvasContent entityID={props.entityID} preview />} 102 121 </div> 103 122 </div> 104 123 ); ··· 114 133 width: `var(--page-width-units)`, 115 134 }} 116 135 > 117 - {blocks.slice(0, 10).map((b, index, arr) => { 118 - return ( 119 - <BlockPreview 120 - pageType="doc" 121 - entityID={b.value} 122 - previousBlock={arr[index - 1] || null} 123 - nextBlock={arr[index + 1] || null} 124 - nextPosition={""} 125 - previewRef={previewRef} 126 - {...b} 127 - key={b.factID} 128 - /> 129 - ); 130 - })} 136 + {isVisible && 137 + blocks.slice(0, 10).map((b, index, arr) => { 138 + return ( 139 + <BlockPreview 140 + pageType="doc" 141 + entityID={b.value} 142 + previousBlock={arr[index - 1] || null} 143 + nextBlock={arr[index + 1] || null} 144 + nextPosition={""} 145 + previewRef={previewRef} 146 + {...b} 147 + key={b.factID} 148 + /> 149 + ); 150 + })} 131 151 </div> 132 152 </div> 133 153 );