links-fe: infinite scroll for link displays

This commit is contained in:
Liam Fitzgerald 2020-12-15 16:46:14 +10:00
parent cd125fc71f
commit 3cfc96c31e
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
4 changed files with 118 additions and 28 deletions

View File

@ -11,6 +11,7 @@ import { RouteComponentProps } from "react-router-dom";
import { LinkItem } from "./components/LinkItem"; import { LinkItem } from "./components/LinkItem";
import LinkSubmit from "./components/LinkSubmit"; import LinkSubmit from "./components/LinkSubmit";
import { LinkPreview } from "./components/link-preview"; import { LinkPreview } from "./components/link-preview";
import { LinkWindow } from "./LinkWindow";
import { Comments } from "~/views/components/Comments"; import { Comments } from "~/views/components/Comments";
import "./css/custom.css"; import "./css/custom.css";
@ -73,16 +74,12 @@ export function LinkResource(props: LinkResourceProps) {
<Col width="100%" flexShrink='0'> <Col width="100%" flexShrink='0'>
<LinkSubmit s3={s3} name={name} ship={ship.slice(1)} api={api} /> <LinkSubmit s3={s3} name={name} ship={ship.slice(1)} api={api} />
</Col> </Col>
{Array.from(graph).map(([date, node]) => { <LinkWindow
const contact = contactDetails[node.post.author];
return (
<LinkItem
association={resource} association={resource}
contacts={contacts} contacts={contacts}
key={date.toString()} key={date.toString()}
resource={resourcePath} resource={resourcePath}
node={node} graph={graph}
contacts={contactDetails}
unreads={unreads} unreads={unreads}
nickname={contact?.nickname} nickname={contact?.nickname}
hideAvatars={hideAvatars} hideAvatars={hideAvatars}

View File

@ -0,0 +1,98 @@
import React, { useRef, useCallback, useEffect } from "react";
import {
Association,
Graph,
Contacts,
Unreads,
LocalUpdateRemoteContentPolicy,
Group,
Rolodex,
} from "~/types";
import GlobalApi from "~/logic/api/global";
import VirtualScroller from "~/views/components/VirtualScroller";
import { LinkItem } from "./components/LinkItem";
interface LinkWindowProps {
association: Association;
contacts: Rolodex;
resource: string;
graph: Graph;
unreads: Unreads;
hideNicknames: boolean;
hideAvatars: boolean;
remoteContentPolicy: LocalUpdateRemoteContentPolicy;
baseUrl: string;
group: Group;
path: string;
api: GlobalApi;
}
export function LinkWindow(props: LinkWindowProps) {
const { graph, api, association } = props;
const loadedNewest = useRef(true);
const loadedOldest = useRef(false);
const virtualList = useRef<VirtualScroller>();
const fetchLinks = useCallback(
async (newer: boolean) => {
/* stubbed, should we generalize the display of graphs in virtualscroller?
* this is copied verbatim from chatwindow
const [, , ship, name] = association["app-path"].split("/");
const currSize = graph.size;
if (newer && !loadedNewest.current) {
const [index] = graph.peekLargest()!;
await api.graph.getYoungerSiblings(
ship,
name,
20,
`/${index.toString()}`
);
if (currSize === graph.size) {
loadedNewest.current = true;
}
} else if (!newer && !loadedOldest.current) {
const [index] = graph.peekSmallest()!;
await api.graph.getOlderSiblings(
ship,
name,
20,
`/${index.toString()}`
);
if (currSize === graph.size) {
console.log("loaded all oldest");
loadedOldest.current = true;
}
}
*/
},
[api, graph, association, loadedNewest, loadedOldest]
);
useEffect(() => {
const list = virtualList?.current;
if(!list) return;
list.calculateVisibleItems();
}, [graph.size])
return (
<VirtualScroller
ref={(l) => (virtualList.current = l ?? undefined)}
origin="top"
style={{ height: "100%" }}
onStartReached={() => {}}
onScroll={() => {}}
data={graph}
size={graph.size}
renderer={({ index, measure, scrollWindow }) => {
const node = graph.get(index);
const post = node?.post;
if (!node || !post) return null;
const isPending = "pending" in post && post.pending;
const linkProps = {
...props,
node,
key: index.toString()
};
return <LinkItem {...linkProps} />;
}}
loadRows={fetchLinks}
/>
);
}

View File

@ -21,7 +21,7 @@ interface LinkItemProps {
api: GlobalApi; api: GlobalApi;
group: Group; group: Group;
path: string; path: string;
contacts: Rolodex[]; contacts: Rolodex;
unreads: Unreads; unreads: Unreads;
} }

View File

@ -141,7 +141,6 @@ export default class VirtualScroller extends Component<VirtualScrollerProps, Vir
const { scrollTop, offsetHeight: windowHeight } = this.window; const { scrollTop, offsetHeight: windowHeight } = this.window;
const { averageHeight } = this.state; const { averageHeight } = this.state;
const { data, size: totalSize, onCalculateVisibleItems } = this.props; const { data, size: totalSize, onCalculateVisibleItems } = this.props;
console.log(windowHeight);
const overscan = Math.max(windowHeight / 2, 200); const overscan = Math.max(windowHeight / 2, 200);
@ -162,10 +161,6 @@ export default class VirtualScroller extends Component<VirtualScrollerProps, Vir
} }
}); });
startBuffer = new BigIntOrderedMap(
[...startBuffer].reverse().slice(0, (visibleItems.size - visibleItems.size % 5))
);
startBuffer.forEach((_datum, index) => { startBuffer.forEach((_datum, index) => {
startgap -= this.heightOf(index); startgap -= this.heightOf(index);
@ -303,7 +298,7 @@ export default class VirtualScroller extends Component<VirtualScrollerProps, Vir
data data
} = this.props; } = this.props;
const indexesToRender = visibleItems.keys().reverse(); const indexesToRender = origin === 'top' ? visibleItems.keys() : visibleItems.keys().reverse();
const transform = origin === 'top' ? 'scale3d(1, 1, 1)' : 'scale3d(1, -1, 1)'; const transform = origin === 'top' ? 'scale3d(1, 1, 1)' : 'scale3d(1, -1, 1)';