latch and unlatch topic stream

This commit is contained in:
Roland Osborne 2022-04-19 00:27:56 -07:00
parent 5816751e11
commit b5df466dc6
3 changed files with 53 additions and 17 deletions

View File

@ -1,9 +1,20 @@
import React, { useEffect } from 'react'; import React, { useEffect, useState } from 'react';
import { TopicItemWrapper } from './TopicItem.styled'; import { TopicItemWrapper } from './TopicItem.styled';
import ReactResizeDetector from 'react-resize-detector'; import ReactResizeDetector from 'react-resize-detector';
export function TopicItem({ topic, padding, onHeight }) { export function TopicItem({ topic, padding, onHeight }) {
const [ text, setText ] = useState(null);
useEffect(() => {
try {
setText(JSON.parse(topic.data.topicDetail.data).text);
}
catch(err) {
console.log("invalid topic", topic);
}
}, [topic]);
return ( return (
<ReactResizeDetector handleHeight={true}> <ReactResizeDetector handleHeight={true}>
{({ height }) => { {({ height }) => {
@ -12,7 +23,7 @@ export function TopicItem({ topic, padding, onHeight }) {
} }
return ( return (
<TopicItemWrapper style={{ paddingTop: padding }}> <TopicItemWrapper style={{ paddingTop: padding }}>
<div>{ JSON.stringify(topic) }</div> <div>{ text }</div>
</TopicItemWrapper> </TopicItemWrapper>
) )
}} }}

View File

@ -13,8 +13,8 @@ export function VirtualList({ topics }) {
const [ viewHeight, setViewHeight ] = useState(DEFAULT_LIST_HEIGHT); const [ viewHeight, setViewHeight ] = useState(DEFAULT_LIST_HEIGHT);
const [ canvasHeight, setCanvasHeight ] = useState(DEFAULT_LIST_HEIGHT*3); const [ canvasHeight, setCanvasHeight ] = useState(DEFAULT_LIST_HEIGHT*3);
const [ items, setItems ] = useState([]); const [ items, setItems ] = useState([]);
const [ scroll, setScroll ] = useState('hidden');
let unlatch = useRef(0);
let latch = useRef(true); let latch = useRef(true);
let scrollTop = useRef(0); let scrollTop = useRef(0);
let containers = useRef([]); let containers = useRef([]);
@ -44,6 +44,15 @@ export function VirtualList({ topics }) {
setTopics(); setTopics();
}, [topics]); }, [topics]);
const onScrollWheel = (e) => {
if (e.deltaY < 0 && latch.current) {
scrollTop.current -= 32;
listRef.current.scrollTo({ top: scrollTop.current, left: 0, behavior: 'smooth' });
setScroll('auto');
latch.current = false;
}
}
const onScrollView = (e) => { const onScrollView = (e) => {
// add or remove from overscan // add or remove from overscan
@ -52,11 +61,19 @@ export function VirtualList({ topics }) {
// set or clear latch // set or clear latch
unlatch.current -= 1;
scrollTop.current = e.target.scrollTop; scrollTop.current = e.target.scrollTop;
loadNextItem();
console.log("UNLATCH: ", unlatch.current); if (!latch.current) {
let view = getPlacement();
if (view?.overscan?.bottom <= 0) {
setScroll('hidden');
latch.current = true;
alignItems();
listRef.current.scrollTo({ top: scrollTop.current, left: 0 });
}
}
loadNextItem();
} }
const loadNextItem = () => { const loadNextItem = () => {
@ -127,16 +144,19 @@ console.log("ADD ITEM AFTER");
let view = getPlacement(); let view = getPlacement();
if (latch.current) { if (latch.current) {
if (view.position.height < viewHeight) { if (view.position.height < viewHeight) {
unlatch.current += 1; if (scrollTop.current != view.position.top) {
listRef.current.scrollTo({ top: view.position.top, left: 0, behavior: 'smooth' }); listRef.current.scrollTo({ top: view.position.top, left: 0, behavior: 'smooth' });
scrollTop.current = view.position.top; scrollTop.current = view.position.top;
} }
}
else { else {
unlatch.current += 1; if (scrollTop.current != view.position.bottom - viewHeight) {
listRef.current.scrollTo({ top: view.position.bottom - viewHeight, left: 0, behavior: 'smooth' }); listRef.current.scrollTo({ top: view.position.bottom - viewHeight, left: 0, behavior: 'smooth' });
scrollTop.current = view.position.bottom - viewHeight; scrollTop.current = view.position.bottom - viewHeight;
} }
} }
console.log("ALIGN: ", scrollTop.current)
}
} }
loadNextItem(); loadNextItem();
@ -149,7 +169,6 @@ console.log("ADD ITEM AFTER");
let view = getPlacement(); let view = getPlacement();
if (!view) { if (!view) {
let pos = canvasHeight / 2; let pos = canvasHeight / 2;
unlatch.current += 1;
listRef.current.scrollTo({ top: pos, left: 0 }); listRef.current.scrollTo({ top: pos, left: 0 });
scrollTop.current = pos; scrollTop.current = pos;
@ -163,7 +182,6 @@ console.log("ADD ITEM AFTER");
containers.current.push(container); containers.current.push(container);
addItemBottom(getItem(container)); addItemBottom(getItem(container));
unlatch.current += 1;
listRef.current.scrollTo({ top: container.top, left: 0, behavior: 'smooth' }); listRef.current.scrollTo({ top: container.top, left: 0, behavior: 'smooth' });
} }
else { else {
@ -205,8 +223,8 @@ console.log("ADD ITEM AFTER");
{({ height }) => { {({ height }) => {
setViewHeight(height); setViewHeight(height);
return ( return (
<VirtualListWrapper onScroll={onScrollView}> <VirtualListWrapper onScroll={onScrollView} onWheel={onScrollWheel}>
<div class="rollview" ref={listRef} onScroll={onScrollView}> <div class="rollview" style={{ overflowY: scroll }} ref={listRef} onScroll={onScrollView}>
<div class="roll" style={{ height: canvasHeight }}> <div class="roll" style={{ height: canvasHeight }}>
{ items } { items }
</div> </div>

View File

@ -7,9 +7,16 @@ export const VirtualListWrapper = styled.div`
overflow: hidden; overflow: hidden;
.rollview { .rollview {
overflow-y: auto;
width: 100%; width: 100%;
height: 100%; height: 100%;
/* hide scrollbar for IE, Edge and Firefox */
-ms-overflow-style: none;
scrollbar-width: none;
}
.rollview::-webkit-scrollbar {
display: none;
} }
.roll { .roll {