this repo has no description
0
fork

Configure Feed

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

Rebuild useScroll, less states

+214 -33
+7
src/app.css
··· 1092 1092 transform: translate(-50%, 0); 1093 1093 font-size: 90%; 1094 1094 pointer-events: auto; 1095 + transition: all 0.3s ease-in-out; 1096 + 1097 + header[hidden] & { 1098 + opacity: 0; 1099 + transform: translate(-50%, -100%) scale(0.9); 1100 + pointer-events: none; 1101 + } 1095 1102 } 1096 1103 .updates-button .icon { 1097 1104 vertical-align: top;
+81 -33
src/components/timeline.jsx
··· 12 12 import useInterval from '../utils/useInterval'; 13 13 import usePageVisibility from '../utils/usePageVisibility'; 14 14 import useScroll from '../utils/useScroll'; 15 + import useScrollFn from '../utils/useScrollFn'; 15 16 16 17 import Icon from './icon'; 17 18 import Link from './link'; ··· 203 204 } 204 205 }); 205 206 206 - const { 207 - scrollDirection, 208 - nearReachStart, 209 - nearReachEnd, 210 - reachStart, 211 - reachEnd, 212 - } = useScroll({ 213 - scrollableRef, 214 - distanceFromEnd: 2, 215 - scrollThresholdStart: 44, 216 - }); 207 + // const { 208 + // scrollDirection, 209 + // nearReachStart, 210 + // nearReachEnd, 211 + // reachStart, 212 + // reachEnd, 213 + // } = useScroll({ 214 + // scrollableRef, 215 + // distanceFromEnd: 2, 216 + // scrollThresholdStart: 44, 217 + // }); 218 + const headerRef = useRef(); 219 + // const [hiddenUI, setHiddenUI] = useState(false); 220 + const [nearReachStart, setNearReachStart] = useState(false); 221 + useScrollFn( 222 + { 223 + scrollableRef, 224 + distanceFromEnd: 2, 225 + scrollThresholdStart: 44, 226 + }, 227 + ({ 228 + scrollDirection, 229 + nearReachStart, 230 + nearReachEnd, 231 + reachStart, 232 + reachEnd, 233 + }) => { 234 + // setHiddenUI(scrollDirection === 'end' && !nearReachEnd); 235 + if (headerRef.current) { 236 + const hiddenUI = scrollDirection === 'end' && !nearReachStart; 237 + headerRef.current.hidden = hiddenUI; 238 + } 239 + setNearReachStart(nearReachStart); 240 + if (reachStart) { 241 + loadItems(true); 242 + } else if (nearReachEnd || (reachEnd && showMore)) { 243 + loadItems(); 244 + } 245 + }, 246 + [], 247 + ); 217 248 218 249 useEffect(() => { 219 250 scrollableRef.current?.scrollTo({ top: 0 }); ··· 223 254 loadItems(true); 224 255 }, [refresh]); 225 256 226 - useEffect(() => { 227 - if (reachStart) { 228 - loadItems(true); 229 - } 230 - }, [reachStart]); 257 + // useEffect(() => { 258 + // if (reachStart) { 259 + // loadItems(true); 260 + // } 261 + // }, [reachStart]); 231 262 232 - useEffect(() => { 233 - if (nearReachEnd || (reachEnd && showMore)) { 234 - loadItems(); 235 - } 236 - }, [nearReachEnd, showMore]); 263 + // useEffect(() => { 264 + // if (nearReachEnd || (reachEnd && showMore)) { 265 + // loadItems(); 266 + // } 267 + // }, [nearReachEnd, showMore]); 237 268 238 269 const prevView = useRef(view); 239 270 useEffect(() => { ··· 304 335 : null, 305 336 ); 306 337 307 - const hiddenUI = scrollDirection === 'end' && !nearReachStart; 338 + // const hiddenUI = scrollDirection === 'end' && !nearReachStart; 308 339 309 340 return ( 310 341 <FilterContext.Provider value={filterContext}> ··· 321 352 > 322 353 <div class="timeline-deck deck"> 323 354 <header 324 - hidden={hiddenUI} 355 + ref={headerRef} 356 + // hidden={hiddenUI} 325 357 onClick={(e) => { 326 358 if (!e.target.closest('a, button')) { 327 359 scrollableRef.current?.scrollTo({ ··· 356 388 </div> 357 389 {items.length > 0 && 358 390 uiState !== 'loading' && 359 - !hiddenUI && 391 + // !hiddenUI && 360 392 showNew && ( 361 393 <button 362 394 class="updates-button shiny-pill" ··· 657 689 658 690 function StatusCarousel({ title, class: className, children }) { 659 691 const carouselRef = useRef(); 660 - const { reachStart, reachEnd, init } = useScroll({ 661 - scrollableRef: carouselRef, 662 - direction: 'horizontal', 663 - }); 664 - useEffect(() => { 665 - init?.(); 666 - }, []); 692 + // const { reachStart, reachEnd, init } = useScroll({ 693 + // scrollableRef: carouselRef, 694 + // direction: 'horizontal', 695 + // }); 696 + const startButtonRef = useRef(); 697 + const endButtonRef = useRef(); 698 + useScrollFn( 699 + { 700 + scrollableRef: carouselRef, 701 + direction: 'horizontal', 702 + init: true, 703 + }, 704 + ({ reachStart, reachEnd }) => { 705 + if (startButtonRef.current) startButtonRef.current.disabled = reachStart; 706 + if (endButtonRef.current) endButtonRef.current.disabled = reachEnd; 707 + }, 708 + [], 709 + ); 710 + // useEffect(() => { 711 + // init?.(); 712 + // }, []); 667 713 668 714 return ( 669 715 <div class={`status-carousel ${className}`}> ··· 671 717 <h3>{title}</h3> 672 718 <span> 673 719 <button 720 + ref={startButtonRef} 674 721 type="button" 675 722 class="small plain2" 676 - disabled={reachStart} 723 + // disabled={reachStart} 677 724 onClick={() => { 678 725 carouselRef.current?.scrollBy({ 679 726 left: -Math.min(320, carouselRef.current?.offsetWidth), ··· 684 731 <Icon icon="chevron-left" /> 685 732 </button>{' '} 686 733 <button 734 + ref={endButtonRef} 687 735 type="button" 688 736 class="small plain2" 689 - disabled={reachEnd} 737 + // disabled={reachEnd} 690 738 onClick={() => { 691 739 carouselRef.current?.scrollBy({ 692 740 left: Math.min(320, carouselRef.current?.offsetWidth),
+126
src/utils/useScrollFn.js
··· 1 + import { useEffect, useLayoutEffect, useState } from 'preact/hooks'; 2 + 3 + export default function useScrollFn( 4 + { 5 + scrollableRef, 6 + distanceFromStart = 1, // ratio of clientHeight/clientWidth 7 + distanceFromEnd = 1, // ratio of clientHeight/clientWidth 8 + scrollThresholdStart = 10, 9 + scrollThresholdEnd = 10, 10 + direction = 'vertical', 11 + distanceFromStartPx: _distanceFromStartPx, 12 + distanceFromEndPx: _distanceFromEndPx, 13 + init, 14 + } = {}, 15 + callback, 16 + deps, 17 + ) { 18 + if (!callback) return; 19 + const [scrollDirection, setScrollDirection] = useState(null); 20 + const [reachStart, setReachStart] = useState(false); 21 + const [reachEnd, setReachEnd] = useState(false); 22 + const [nearReachStart, setNearReachStart] = useState(false); 23 + const [nearReachEnd, setNearReachEnd] = useState(false); 24 + const isVertical = direction === 'vertical'; 25 + 26 + useLayoutEffect(() => { 27 + const scrollableElement = scrollableRef.current; 28 + if (!scrollableElement) return {}; 29 + let previousScrollStart = isVertical 30 + ? scrollableElement.scrollTop 31 + : scrollableElement.scrollLeft; 32 + 33 + function onScroll() { 34 + const { 35 + scrollTop, 36 + scrollLeft, 37 + scrollHeight, 38 + scrollWidth, 39 + clientHeight, 40 + clientWidth, 41 + } = scrollableElement; 42 + const scrollStart = isVertical ? scrollTop : scrollLeft; 43 + const scrollDimension = isVertical ? scrollHeight : scrollWidth; 44 + const clientDimension = isVertical ? clientHeight : clientWidth; 45 + const scrollDistance = Math.abs(scrollStart - previousScrollStart); 46 + const distanceFromStartPx = 47 + _distanceFromStartPx || 48 + Math.min( 49 + clientDimension * distanceFromStart, 50 + scrollDimension, 51 + scrollStart, 52 + ); 53 + const distanceFromEndPx = 54 + _distanceFromEndPx || 55 + Math.min( 56 + clientDimension * distanceFromEnd, 57 + scrollDimension, 58 + scrollDimension - scrollStart - clientDimension, 59 + ); 60 + 61 + if ( 62 + scrollDistance >= 63 + (previousScrollStart < scrollStart 64 + ? scrollThresholdEnd 65 + : scrollThresholdStart) 66 + ) { 67 + setScrollDirection(previousScrollStart < scrollStart ? 'end' : 'start'); 68 + previousScrollStart = scrollStart; 69 + } 70 + 71 + setReachStart(scrollStart <= 0); 72 + setReachEnd(scrollStart + clientDimension >= scrollDimension); 73 + setNearReachStart(scrollStart <= distanceFromStartPx); 74 + setNearReachEnd( 75 + scrollStart + clientDimension >= scrollDimension - distanceFromEndPx, 76 + ); 77 + } 78 + 79 + scrollableElement.addEventListener('scroll', onScroll, { passive: true }); 80 + 81 + return () => scrollableElement.removeEventListener('scroll', onScroll); 82 + }, [ 83 + distanceFromStart, 84 + distanceFromEnd, 85 + scrollThresholdStart, 86 + scrollThresholdEnd, 87 + ]); 88 + 89 + useEffect(() => { 90 + callback({ 91 + scrollDirection, 92 + reachStart, 93 + reachEnd, 94 + nearReachStart, 95 + nearReachEnd, 96 + }); 97 + }, [ 98 + scrollDirection, 99 + reachStart, 100 + reachEnd, 101 + nearReachStart, 102 + nearReachEnd, 103 + ...deps, 104 + ]); 105 + 106 + useEffect(() => { 107 + if (init && scrollableRef.current) { 108 + queueMicrotask(() => { 109 + scrollableRef.current.dispatchEvent(new Event('scroll')); 110 + }); 111 + } 112 + }, [init]); 113 + 114 + // return { 115 + // scrollDirection, 116 + // reachStart, 117 + // reachEnd, 118 + // nearReachStart, 119 + // nearReachEnd, 120 + // init: () => { 121 + // if (scrollableRef.current) { 122 + // scrollableRef.current.dispatchEvent(new Event('scroll')); 123 + // } 124 + // }, 125 + // }; 126 + }