Prep for infinite scroll
parent
5bed926323
commit
9757983046
|
@ -35,11 +35,19 @@ class SubscriptionManager {
|
||||||
return db.subscriptions.toCollection().first(); // May be undefined
|
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
|
return db.notifications
|
||||||
.where({ subscriptionId: subscriptionId })
|
.orderBy("time") // Sort by time first
|
||||||
|
.filter(n => n.subscriptionId === subscriptionId)
|
||||||
|
.offset(offset)
|
||||||
|
.limit(pageSize)
|
||||||
.reverse()
|
.reverse()
|
||||||
.sortBy("time"); // Inefficient, but there is no other way (see docs)
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllNotifications() {
|
async getAllNotifications() {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import Toolbar from "@mui/material/Toolbar";
|
||||||
import Divider from "@mui/material/Divider";
|
import Divider from "@mui/material/Divider";
|
||||||
import List from "@mui/material/List";
|
import List from "@mui/material/List";
|
||||||
import SettingsIcon from "@mui/icons-material/Settings";
|
import SettingsIcon from "@mui/icons-material/Settings";
|
||||||
import HomeIcon from '@mui/icons-material/Home';
|
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import SubscribeDialog from "./SubscribeDialog";
|
import SubscribeDialog from "./SubscribeDialog";
|
||||||
import {Alert, AlertTitle, Badge, CircularProgress, ListSubheader} from "@mui/material";
|
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 {ConnectionState} from "../app/Connection";
|
||||||
import {useLocation, useNavigate} from "react-router-dom";
|
import {useLocation, useNavigate} from "react-router-dom";
|
||||||
import subscriptionManager from "../app/SubscriptionManager";
|
import subscriptionManager from "../app/SubscriptionManager";
|
||||||
|
import {ChatBubble} from "@mui/icons-material";
|
||||||
|
|
||||||
const navWidth = 240;
|
const navWidth = 240;
|
||||||
|
|
||||||
|
@ -81,19 +81,24 @@ const NavList = (props) => {
|
||||||
<Toolbar sx={{ display: { xs: 'none', sm: 'block' } }}/>
|
<Toolbar sx={{ display: { xs: 'none', sm: 'block' } }}/>
|
||||||
<List component="nav" sx={{ paddingTop: (showGrantPermissionsBox) ? '0' : '' }}>
|
<List component="nav" sx={{ paddingTop: (showGrantPermissionsBox) ? '0' : '' }}>
|
||||||
{showGrantPermissionsBox && <PermissionAlert onRequestPermissionClick={props.requestNotificationPermission}/>}
|
{showGrantPermissionsBox && <PermissionAlert onRequestPermissionClick={props.requestNotificationPermission}/>}
|
||||||
|
{!showSubscriptionsList &&
|
||||||
|
<ListItemButton onClick={() => navigate("/")} selected={location.pathname === "/"}>
|
||||||
|
<ListItemIcon><ChatBubble/></ListItemIcon>
|
||||||
|
<ListItemText primary="All notifications"/>
|
||||||
|
</ListItemButton>}
|
||||||
{showSubscriptionsList &&
|
{showSubscriptionsList &&
|
||||||
<>
|
<>
|
||||||
<ListSubheader>Subscribed topics</ListSubheader>
|
<ListSubheader>Subscribed topics</ListSubheader>
|
||||||
|
<ListItemButton onClick={() => navigate("/")} selected={location.pathname === "/"}>
|
||||||
|
<ListItemIcon><ChatBubble/></ListItemIcon>
|
||||||
|
<ListItemText primary="All notifications"/>
|
||||||
|
</ListItemButton>
|
||||||
<SubscriptionList
|
<SubscriptionList
|
||||||
subscriptions={props.subscriptions}
|
subscriptions={props.subscriptions}
|
||||||
selectedSubscription={props.selectedSubscription}
|
selectedSubscription={props.selectedSubscription}
|
||||||
/>
|
/>
|
||||||
<Divider sx={{my: 1}}/>
|
<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"}>
|
<ListItemButton onClick={() => navigate("/settings")} selected={location.pathname === "/settings"}>
|
||||||
<ListItemIcon><SettingsIcon/></ListItemIcon>
|
<ListItemIcon><SettingsIcon/></ListItemIcon>
|
||||||
<ListItemText primary="Settings"/>
|
<ListItemText primary="Settings"/>
|
||||||
|
|
|
@ -40,19 +40,18 @@ const AllSubscriptions = () => {
|
||||||
|
|
||||||
const SingleSubscription = (props) => {
|
const SingleSubscription = (props) => {
|
||||||
const subscription = props.subscription;
|
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) {
|
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}/>;
|
return <NotificationList notifications={notifications} onScroll={() => setOffset(prev => prev + 20)}/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NotificationList = (props) => {
|
const NotificationList = (props) => {
|
||||||
const sortedNotifications = props.notifications;
|
const sortedNotifications = props.notifications;
|
||||||
/*const sortedNotifications = Array.from(props.notifications)
|
|
||||||
.sort((a, b) => a.time < b.time ? 1 : -1);*/
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="md" sx={{marginTop: 3, marginBottom: 3}}>
|
<Container maxWidth="md" sx={{marginTop: 3, marginBottom: 3}}>
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
|
|
Loading…
Reference in New Issue