an appview-less Bluesky client using Constellation and PDS Queries reddwarf.app
frontend spa bluesky reddwarf microcosm

possible scroll fix

rimar1337 44b8e6c2 9f8a63c5

Changed files
+27 -36
src
routes
profile.$did
+27 -36
src/routes/profile.$did/post.$rkey.tsx
··· 40 40 did, 41 41 rkey, 42 42 nopics, 43 - lightboxCallback 43 + lightboxCallback, 44 44 }: { 45 45 did: string; 46 46 rkey: string; 47 47 nopics?: boolean; 48 - lightboxCallback?: (d:LightboxProps) => void; 48 + lightboxCallback?: (d: LightboxProps) => void; 49 49 }) { 50 50 //const { get, set } = usePersistentStore(); 51 51 const queryClient = useQueryClient(); ··· 260 260 replyAturis.unshift(oldestOpsReply); 261 261 } 262 262 263 - 264 263 const [parents, setParents] = React.useState<any[]>([]); 265 264 const [parentsLoading, setParentsLoading] = React.useState(false); 266 265 267 266 const mainPostRef = React.useRef<HTMLDivElement>(null); 268 - const userHasScrolled = React.useRef(false); 267 + const hasPerformedInitialLayout = React.useRef(false); 268 + 269 + const [layoutReady, setLayoutReady] = React.useState(false); 270 + 271 + useLayoutEffect(() => { 272 + if (parents.length > 0 && !layoutReady && mainPostRef.current) { 273 + const mainPostElement = mainPostRef.current; 274 + 275 + if (window.scrollY === 0 && !hasPerformedInitialLayout.current) { 276 + const elementTop = mainPostElement.getBoundingClientRect().top; 277 + const headerOffset = 70; 269 278 270 - const scrollAnchor = React.useRef<{ top: number } | null>(null); 279 + const targetScrollY = elementTop - headerOffset; 271 280 272 - React.useEffect(() => { 273 - const onScroll = () => { 274 - if (window.scrollY > 50) { 275 - userHasScrolled.current = true; 281 + window.scrollBy(0, targetScrollY); 276 282 277 - window.removeEventListener("scroll", onScroll); 283 + hasPerformedInitialLayout.current = true; 278 284 } 279 - }; 280 - 281 - if (!userHasScrolled.current) { 282 - window.addEventListener("scroll", onScroll, { passive: true }); 285 + // todo idk what to do with this 286 + setLayoutReady(true); 283 287 } 284 - return () => window.removeEventListener("scroll", onScroll); 285 - }, []); 288 + }, [parents, layoutReady]); 286 289 287 - useLayoutEffect(() => { 288 - if (parentsLoading && mainPostRef.current && !userHasScrolled.current) { 289 - scrollAnchor.current = { 290 - top: mainPostRef.current.getBoundingClientRect().top, 291 - }; 290 + React.useEffect(() => { 291 + if (parentsLoading) { 292 + setLayoutReady(false); 292 293 } 293 - }, [parentsLoading]); 294 294 295 - useLayoutEffect(() => { 296 - if ( 297 - scrollAnchor.current && 298 - mainPostRef.current && 299 - !userHasScrolled.current 300 - ) { 301 - const newTop = mainPostRef.current.getBoundingClientRect().top; 302 - const topDiff = newTop - scrollAnchor.current.top; 303 - if (topDiff > 0) { 304 - window.scrollBy(0, topDiff); 305 - } 306 - scrollAnchor.current = null; 295 + if (!mainPost?.value?.reply?.parent?.uri && !parentsLoading) { 296 + setLayoutReady(true); 297 + hasPerformedInitialLayout.current = true; 307 298 } 308 - }, [parents]); 299 + }, [parentsLoading, mainPost]); 309 300 310 301 React.useEffect(() => { 311 302 if (!mainPost?.value?.reply?.parent?.uri) { ··· 407 398 //margin: "0px auto 0", 408 399 padding: 0, 409 400 minHeight: "80dvh", 410 - paddingBottom: "20dvh" 401 + paddingBottom: "20dvh", 411 402 }} 412 403 > 413 404 <div