mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-02 07:06:41 +03:00
Inbox: make useLazyScroll account for archived notifications
useLazyScroll was not accounting for the case where a notification would be archived. This would mean that archiving a lot of notifications without scrolling would erroneously not load more. Accounts for this case by passing a count argument to useLazyScroll, which is then compared against its previous value. If the previous value is greater than the new value, (i.e. a notification was archived) then check if we should load more.
This commit is contained in:
parent
71ae452132
commit
003738f95a
@ -1,5 +1,6 @@
|
||||
import { useEffect, RefObject, useRef, useState } from "react";
|
||||
import _ from "lodash";
|
||||
import usePreviousValue from "./usePreviousValue";
|
||||
|
||||
export function distanceToBottom(el: HTMLElement) {
|
||||
const { scrollTop, scrollHeight, clientHeight } = el;
|
||||
@ -11,28 +12,41 @@ export function distanceToBottom(el: HTMLElement) {
|
||||
export function useLazyScroll(
|
||||
ref: RefObject<HTMLElement>,
|
||||
margin: number,
|
||||
count: number,
|
||||
loadMore: () => Promise<boolean>
|
||||
) {
|
||||
const [isDone, setIsDone] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const oldCount = usePreviousValue(count);
|
||||
const loadUntil = (el: HTMLElement) => {
|
||||
if (!isDone && distanceToBottom(el) < margin) {
|
||||
setIsLoading(true);
|
||||
return loadMore().then((done) => {
|
||||
setIsLoading(false);
|
||||
if (done) {
|
||||
setIsDone(true);
|
||||
return Promise.resolve();
|
||||
}
|
||||
return loadUntil(el);
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if((oldCount > count) && ref.current) {
|
||||
loadUntil(ref.current);
|
||||
}
|
||||
}, [count]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!ref.current) {
|
||||
return;
|
||||
}
|
||||
setIsDone(false);
|
||||
const scroll = ref.current;
|
||||
const loadUntil = (el: HTMLElement) => {
|
||||
if (!isDone && distanceToBottom(el) < margin) {
|
||||
return loadMore().then((done) => {
|
||||
if (done) {
|
||||
setIsDone(true);
|
||||
return Promise.resolve();
|
||||
}
|
||||
return loadUntil(el);
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
loadUntil(scroll);
|
||||
|
||||
const onScroll = (e: Event) => {
|
||||
@ -40,12 +54,13 @@ export function useLazyScroll(
|
||||
loadUntil(el);
|
||||
};
|
||||
|
||||
ref.current.addEventListener("scroll", onScroll);
|
||||
ref.current.addEventListener("scroll", onScroll, { passive: true });
|
||||
|
||||
return () => {
|
||||
ref.current?.removeEventListener("scroll", onScroll);
|
||||
};
|
||||
}, [ref?.current]);
|
||||
}, [ref?.current, count]);
|
||||
|
||||
|
||||
return isDone;
|
||||
return { isDone, isLoading };
|
||||
}
|
||||
|
@ -385,7 +385,12 @@ function archive(json: any, state: HarkState) {
|
||||
const [archived, unarchived] = _.partition(timebox, (idxNotif) =>
|
||||
notifIdxEqual(index, idxNotif.index)
|
||||
);
|
||||
state.notifications.set(time, unarchived);
|
||||
if(unarchived.length === 0) {
|
||||
console.log('deleting entire timebox');
|
||||
state.notifications.delete(time);
|
||||
} else {
|
||||
state.notifications.set(time, unarchived);
|
||||
}
|
||||
const newlyRead = archived.filter(x => !x.notification.read).length;
|
||||
updateNotificationStats(state, index, 'notifications', (x) => x - newlyRead);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useCallback, useRef, useState } from "react";
|
||||
import f from "lodash/fp";
|
||||
import _ from "lodash";
|
||||
import { Icon, Col, Row, Box, Text, Anchor, Rule, Center } from "@tlon/indigo-react";
|
||||
import { Icon, Col, Row, Box, Text, Anchor, Rule, Center, LoadingSpinner } from "@tlon/indigo-react";
|
||||
import moment from "moment";
|
||||
import { Notifications, Rolodex, Timebox, IndexedNotification, Groups, GroupNotificationsConfig, NotificationGraphConfig } from "~/types";
|
||||
import { MOMENT_CALENDAR_DATE, daToUnix, resourceAsPath } from "~/logic/lib/util";
|
||||
@ -35,6 +35,7 @@ function filterNotification(associations: Associations, groups: string[]) {
|
||||
|
||||
export default function Inbox(props: {
|
||||
notifications: Notifications;
|
||||
notificationsSize: number;
|
||||
archive: Notifications;
|
||||
groups: Groups;
|
||||
showArchive?: boolean;
|
||||
@ -99,7 +100,12 @@ export default function Inbox(props: {
|
||||
return api.hark.getMore();
|
||||
}, [api]);
|
||||
|
||||
const loadedAll = useLazyScroll(scrollRef, 0.2, loadMore);
|
||||
const { isDone, isLoading } = useLazyScroll(
|
||||
scrollRef,
|
||||
0.2,
|
||||
_.flatten(notifications).length,
|
||||
loadMore
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
@ -122,11 +128,17 @@ export default function Inbox(props: {
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{loadedAll && (
|
||||
{isDone && (
|
||||
<Center mt="2" borderTop={notifications.length !== 0 ? 1 : 0} borderTopColor="washedGray" width="100%" height="96px">
|
||||
<Text gray fontSize="1">No more notifications</Text>
|
||||
</Center>
|
||||
)}
|
||||
{isLoading && (
|
||||
<Center mt="2" borderTop={notifications.length !== 0 ? 1 : 0} borderTopColor="washedGray" width="100%" height="96px">
|
||||
<LoadingSpinner />
|
||||
</Center>
|
||||
)}
|
||||
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user