Prep for infinite scroll

This commit is contained in:
Philipp Heckel 2022-03-07 20:11:58 -05:00
parent 5bed926323
commit 9757983046
3 changed files with 24 additions and 12 deletions

View file

@ -35,11 +35,19 @@ class SubscriptionManager {
return db.subscriptions.toCollection().first(); // May be undefined
}
async getNotifications(subscriptionId) {
async getNotifications(subscriptionId, offset) {
// 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
// killing performance. See https://dexie.org/docs/Collection/Collection.offset()#a-better-paging-approach
const pageSize = 20;
return db.notifications
.where({ subscriptionId: subscriptionId })
.orderBy("time") // Sort by time first
.filter(n => n.subscriptionId === subscriptionId)
.offset(offset)
.limit(pageSize)
.reverse()
.sortBy("time"); // Inefficient, but there is no other way (see docs)
.toArray();
}
async getAllNotifications() {

View file

@ -9,7 +9,6 @@ import Toolbar from "@mui/material/Toolbar";
import Divider from "@mui/material/Divider";
import List from "@mui/material/List";
import SettingsIcon from "@mui/icons-material/Settings";
import HomeIcon from '@mui/icons-material/Home';
import AddIcon from "@mui/icons-material/Add";
import SubscribeDialog from "./SubscribeDialog";
import {Alert, AlertTitle, Badge, CircularProgress, ListSubheader} from "@mui/material";
@ -19,6 +18,7 @@ import {subscriptionRoute, topicShortUrl, topicUrl} from "../app/utils";
import {ConnectionState} from "../app/Connection";
import {useLocation, useNavigate} from "react-router-dom";
import subscriptionManager from "../app/SubscriptionManager";
import {ChatBubble} from "@mui/icons-material";
const navWidth = 240;
@ -81,19 +81,24 @@ const NavList = (props) => {
<Toolbar sx={{ display: { xs: 'none', sm: 'block' } }}/>
<List component="nav" sx={{ paddingTop: (showGrantPermissionsBox) ? '0' : '' }}>
{showGrantPermissionsBox && <PermissionAlert onRequestPermissionClick={props.requestNotificationPermission}/>}
{!showSubscriptionsList &&
<ListItemButton onClick={() => navigate("/")} selected={location.pathname === "/"}>
<ListItemIcon><ChatBubble/></ListItemIcon>
<ListItemText primary="All notifications"/>
</ListItemButton>}
{showSubscriptionsList &&
<>
<ListSubheader>Subscribed topics</ListSubheader>
<ListItemButton onClick={() => navigate("/")} selected={location.pathname === "/"}>
<ListItemIcon><ChatBubble/></ListItemIcon>
<ListItemText primary="All notifications"/>
</ListItemButton>
<SubscriptionList
subscriptions={props.subscriptions}
selectedSubscription={props.selectedSubscription}
/>
<Divider sx={{my: 1}}/>
</>}
<ListItemButton onClick={() => navigate("/")} selected={location.pathname === "/"}>
<ListItemIcon><HomeIcon/></ListItemIcon>
<ListItemText primary="Home"/>
</ListItemButton>
<ListItemButton onClick={() => navigate("/settings")} selected={location.pathname === "/settings"}>
<ListItemIcon><SettingsIcon/></ListItemIcon>
<ListItemText primary="Settings"/>

View file

@ -40,19 +40,18 @@ const AllSubscriptions = () => {
const SingleSubscription = (props) => {
const subscription = props.subscription;
const notifications = useLiveQuery(() => subscriptionManager.getNotifications(subscription.id), [subscription]);
const [offset, setOffset] = useState(0);
const notifications = useLiveQuery(() => subscriptionManager.getNotifications(subscription.id, offset), [subscription, offset]);
if (notifications === null || notifications === undefined) {
return <Loading/>;
} else if (notifications.length === 0) {
return <NoNotifications subscription={subscription}/>;
}
return <NotificationList notifications={notifications}/>;
return <NotificationList notifications={notifications} onScroll={() => setOffset(prev => prev + 20)}/>;
}
const NotificationList = (props) => {
const sortedNotifications = props.notifications;
/*const sortedNotifications = Array.from(props.notifications)
.sort((a, b) => a.time < b.time ? 1 : -1);*/
return (
<Container maxWidth="md" sx={{marginTop: 3, marginBottom: 3}}>
<Stack spacing={3}>