mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 16:51:42 +03:00
links-fe: infinite scroll for link displays
This commit is contained in:
parent
cd125fc71f
commit
3cfc96c31e
@ -11,6 +11,7 @@ import { RouteComponentProps } from "react-router-dom";
|
||||
import { LinkItem } from "./components/LinkItem";
|
||||
import LinkSubmit from "./components/LinkSubmit";
|
||||
import { LinkPreview } from "./components/link-preview";
|
||||
import { LinkWindow } from "./LinkWindow";
|
||||
import { Comments } from "~/views/components/Comments";
|
||||
|
||||
import "./css/custom.css";
|
||||
@ -73,16 +74,12 @@ export function LinkResource(props: LinkResourceProps) {
|
||||
<Col width="100%" flexShrink='0'>
|
||||
<LinkSubmit s3={s3} name={name} ship={ship.slice(1)} api={api} />
|
||||
</Col>
|
||||
{Array.from(graph).map(([date, node]) => {
|
||||
const contact = contactDetails[node.post.author];
|
||||
return (
|
||||
<LinkItem
|
||||
<LinkWindow
|
||||
association={resource}
|
||||
contacts={contacts}
|
||||
key={date.toString()}
|
||||
resource={resourcePath}
|
||||
node={node}
|
||||
contacts={contactDetails}
|
||||
graph={graph}
|
||||
unreads={unreads}
|
||||
nickname={contact?.nickname}
|
||||
hideAvatars={hideAvatars}
|
||||
|
98
pkg/interface/src/views/apps/links/LinkWindow.tsx
Normal file
98
pkg/interface/src/views/apps/links/LinkWindow.tsx
Normal 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}
|
||||
/>
|
||||
);
|
||||
}
|
@ -21,7 +21,7 @@ interface LinkItemProps {
|
||||
api: GlobalApi;
|
||||
group: Group;
|
||||
path: string;
|
||||
contacts: Rolodex[];
|
||||
contacts: Rolodex;
|
||||
unreads: Unreads;
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,6 @@ export default class VirtualScroller extends Component<VirtualScrollerProps, Vir
|
||||
const { scrollTop, offsetHeight: windowHeight } = this.window;
|
||||
const { averageHeight } = this.state;
|
||||
const { data, size: totalSize, onCalculateVisibleItems } = this.props;
|
||||
console.log(windowHeight);
|
||||
|
||||
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) => {
|
||||
startgap -= this.heightOf(index);
|
||||
@ -303,7 +298,7 @@ export default class VirtualScroller extends Component<VirtualScrollerProps, Vir
|
||||
data
|
||||
} = 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)';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user