make notifications togglable

This commit is contained in:
hzrd149
2024-09-06 07:47:54 -05:00
parent a016adfca6
commit a12621d7d8
3 changed files with 31 additions and 13 deletions

View File

@ -1,5 +1,5 @@
--- ---
"nostrudel": minor "nostrudel": patch
--- ---
Improve notifications timeline rendering performance Improve notifications timeline rendering performance

View File

@ -1,4 +1,14 @@
import { PropsWithChildren, ReactNode, forwardRef, memo, useCallback, useContext, useEffect, useRef } from "react"; import {
MouseEventHandler,
PropsWithChildren,
ReactNode,
forwardRef,
memo,
useCallback,
useContext,
useEffect,
useRef,
} from "react";
import { Box, Flex, Spacer, Text, useColorModeValue } from "@chakra-ui/react"; import { Box, Flex, Spacer, Text, useColorModeValue } from "@chakra-ui/react";
import dayjs from "dayjs"; import dayjs from "dayjs";
@ -8,6 +18,7 @@ import UserName from "../../../components/user/user-name";
import { CheckIcon } from "../../../components/icons"; import { CheckIcon } from "../../../components/icons";
import FocusedContext from "../focused-context"; import FocusedContext from "../focused-context";
import useReadStatus from "../../../hooks/use-read-status"; import useReadStatus from "../../../hooks/use-read-status";
import { usePrevious } from "react-use";
const ONE_MONTH = dayjs().add(1, "month").unix(); const ONE_MONTH = dayjs().add(1, "month").unix();
@ -28,18 +39,25 @@ const NotificationIconEntry = memo(
const focusColor = useColorModeValue("blackAlpha.100", "whiteAlpha.100"); const focusColor = useColorModeValue("blackAlpha.100", "whiteAlpha.100");
const expanded = focused === id; const expanded = focused === id;
const focusSelf = useCallback(() => focus(id), [id, focus]);
// scroll element to stop when opened
const headerRef = useRef<HTMLDivElement | null>(null); const headerRef = useRef<HTMLDivElement | null>(null);
const handleClick = useCallback<MouseEventHandler<HTMLDivElement>>(
(e) => {
focus(expanded ? "" : id);
if (onClick) onClick();
},
[id, focus, expanded],
);
// scroll into view when opened
const prev = usePrevious(focused);
useEffect(() => { useEffect(() => {
if (expanded) { if (prev && prev !== focused && focused === id) {
setTimeout(() => { setTimeout(() => {
headerRef.current?.scrollIntoView(); headerRef.current?.scrollIntoView();
}, 2); }, 2);
} }
}, [expanded]); }, [prev, focused]);
// set read when expanded // set read when expanded
useEffect(() => { useEffect(() => {
@ -61,8 +79,7 @@ const NotificationIconEntry = memo(
cursor="pointer" cursor="pointer"
p="2" p="2"
tabIndex={0} tabIndex={0}
onFocus={onClick ? undefined : focusSelf} onClick={handleClick}
onClick={onClick}
userSelect="none" userSelect="none"
bg={!read ? focusColor : undefined} bg={!read ? focusColor : undefined}
ref={headerRef} ref={headerRef}

View File

@ -67,7 +67,7 @@ const NotificationsTimeline = memo(
const cacheKey = useTimelineLocationCacheKey(); const cacheKey = useTimelineLocationCacheKey();
const numberCache = useNumberCache(cacheKey); const numberCache = useNumberCache(cacheKey);
const minItems = Math.round(window.innerHeight / 48); const minItems = Math.round(window.innerHeight / 48) * 2;
const dates = useTimelineDates(events, numberCache, minItems / 2, minItems); const dates = useTimelineDates(events, numberCache, minItems / 2, minItems);
// measure and cache the hight of every entry // measure and cache the hight of every entry
@ -115,13 +115,14 @@ const NotificationsTimeline = memo(
items.push(<TimeMarker key={prev.unix() + "-marker"} date={prev} ids={ids} />); items.push(<TimeMarker key={prev.unix() + "-marker"} date={prev} ids={ids} />);
} }
const visible = event.created_at <= dates.max && event.created_at >= dates.min;
ids.push(event.id); ids.push(event.id);
items.push( items.push(
<NotificationItem <NotificationItem
key={event.id} key={event.id}
event={event} event={event}
visible={event.created_at <= dates.max && event.created_at >= dates.min} visible={visible}
minHeight={numberCache.get(getEventUID(event)) + "px"} minHeight={visible ? undefined : numberCache.get(getEventUID(event)) + "px"}
/>, />,
); );
} }