Working infinite scroll

This commit is contained in:
Philipp Heckel 2022-03-08 11:21:11 -05:00
parent 6d140d6a86
commit 30b13cbdbc
2 changed files with 20 additions and 18 deletions

View file

@ -35,18 +35,14 @@ class SubscriptionManager {
return db.subscriptions.toCollection().first(); // May be undefined return db.subscriptions.toCollection().first(); // May be undefined
} }
async getNotifications(subscriptionId, offset) { async getNotifications(subscriptionId) {
// This is quite awkward, but it is the recommended approach as per the Dexie docs. // This is quite awkward, but it is the recommended approach as per the Dexie docs.
// It's actually fine, because the reading and filtering is quite fast. The rendering is what's // It's actually fine, because the reading and filtering is quite fast. The rendering is what's
// killing performance. See https://dexie.org/docs/Collection/Collection.offset()#a-better-paging-approach // killing performance. See https://dexie.org/docs/Collection/Collection.offset()#a-better-paging-approach
console.log(`getNotifications(${subscriptionId}, ${offset})`)
const pageSize = 2000;
return db.notifications return db.notifications
.orderBy("time") // Sort by time first .orderBy("time") // Sort by time first
.filter(n => n.subscriptionId === subscriptionId) .filter(n => n.subscriptionId === subscriptionId)
.offset(offset)
.limit(pageSize)
.reverse() .reverse()
.toArray(); .toArray();
} }

View file

@ -3,7 +3,7 @@ import {ButtonBase, CardActions, CardContent, CircularProgress, Fade, Link, Moda
import Card from "@mui/material/Card"; import Card from "@mui/material/Card";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import * as React from "react"; import * as React from "react";
import {useState} from "react"; import {useEffect, useState} from "react";
import { import {
formatBytes, formatBytes,
formatMessage, formatMessage,
@ -36,37 +36,43 @@ const AllSubscriptions = () => {
} else if (notifications.length === 0) { } else if (notifications.length === 0) {
return <NoSubscriptions/>; return <NoSubscriptions/>;
} }
return <NotificationList notifications={notifications}/>; return <NotificationList key="all" notifications={notifications}/>;
} }
const SingleSubscription = (props) => { const SingleSubscription = (props) => {
const subscription = props.subscription; const subscription = props.subscription;
const [offset, setOffset] = useState(0); const notifications = useLiveQuery(() => subscriptionManager.getNotifications(subscription.id), [subscription]);
const notifications = useLiveQuery(() => subscriptionManager.getNotifications(subscription.id, offset), [subscription, offset]);
if (notifications === null || notifications === undefined) { if (notifications === null || notifications === undefined) {
return <Loading/>; return <Loading/>;
} else if (notifications.length === 0) { } else if (notifications.length === 0) {
return <NoNotifications subscription={subscription}/>; return <NoNotifications subscription={subscription}/>;
} }
return <NotificationList notifications={notifications} onFetch={() => { return <NotificationList id={subscription.id} notifications={notifications}/>;
console.log(`setOffset`)
setOffset(prev => prev + 20)
}}/>;
} }
const NotificationList = (props) => { const NotificationList = (props) => {
const notifications = props.notifications;
const pageSize = 20; const pageSize = 20;
const [count, setCount] = useState(Math.min(notifications.length, pageSize)); const notifications = props.notifications;
const [maxCount, setMaxCount] = useState(pageSize);
// Reset state when the list identifier changes, i.e when we switch between subscriptions
useEffect(() => {
return () => {
setMaxCount(pageSize);
document.getElementById("main").scrollTo(0, 0);
}
}, [props.id]);
const count = Math.min(notifications.length, maxCount);
console.log(`xxx id=${props.id} scrollMax=${maxCount} count=${count} len=${notifications.length}`)
console.log(`count ${count}`)
return ( return (
<InfiniteScroll <InfiniteScroll
dataLength={count} dataLength={count}
next={() => setCount(prev => Math.min(notifications.length, prev + 20))} next={() => setMaxCount(prev => prev + pageSize)}
hasMore={count < notifications.length} hasMore={count < notifications.length}
loader={<h1>aa</h1>} loader={<h1>aa</h1>}
scrollThreshold="400px" scrollThreshold={0.7}
scrollableTarget="main" scrollableTarget="main"
> >
<Container maxWidth="md" sx={{marginTop: 3, marginBottom: 3}}> <Container maxWidth="md" sx={{marginTop: 3, marginBottom: 3}}>