From a12621d7d87fda86db8843c9143d927b3b9de76f Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Fri, 6 Sep 2024 07:47:54 -0500 Subject: [PATCH] make notifications togglable --- .changeset/tiny-planets-cheat.md | 2 +- .../components/notification-icon-entry.tsx | 35 ++++++++++++++----- src/views/notifications/index.tsx | 7 ++-- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/.changeset/tiny-planets-cheat.md b/.changeset/tiny-planets-cheat.md index ecefbaae6..61ced466a 100644 --- a/.changeset/tiny-planets-cheat.md +++ b/.changeset/tiny-planets-cheat.md @@ -1,5 +1,5 @@ --- -"nostrudel": minor +"nostrudel": patch --- Improve notifications timeline rendering performance diff --git a/src/views/notifications/components/notification-icon-entry.tsx b/src/views/notifications/components/notification-icon-entry.tsx index dfaa33ebc..2ed665ea7 100644 --- a/src/views/notifications/components/notification-icon-entry.tsx +++ b/src/views/notifications/components/notification-icon-entry.tsx @@ -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 dayjs from "dayjs"; @@ -8,6 +18,7 @@ import UserName from "../../../components/user/user-name"; import { CheckIcon } from "../../../components/icons"; import FocusedContext from "../focused-context"; import useReadStatus from "../../../hooks/use-read-status"; +import { usePrevious } from "react-use"; const ONE_MONTH = dayjs().add(1, "month").unix(); @@ -28,18 +39,25 @@ const NotificationIconEntry = memo( const focusColor = useColorModeValue("blackAlpha.100", "whiteAlpha.100"); const expanded = focused === id; - - const focusSelf = useCallback(() => focus(id), [id, focus]); - - // scroll element to stop when opened const headerRef = useRef(null); + + const handleClick = useCallback>( + (e) => { + focus(expanded ? "" : id); + if (onClick) onClick(); + }, + [id, focus, expanded], + ); + + // scroll into view when opened + const prev = usePrevious(focused); useEffect(() => { - if (expanded) { + if (prev && prev !== focused && focused === id) { setTimeout(() => { headerRef.current?.scrollIntoView(); }, 2); } - }, [expanded]); + }, [prev, focused]); // set read when expanded useEffect(() => { @@ -61,8 +79,7 @@ const NotificationIconEntry = memo( cursor="pointer" p="2" tabIndex={0} - onFocus={onClick ? undefined : focusSelf} - onClick={onClick} + onClick={handleClick} userSelect="none" bg={!read ? focusColor : undefined} ref={headerRef} diff --git a/src/views/notifications/index.tsx b/src/views/notifications/index.tsx index 348ee420e..75b3719fd 100644 --- a/src/views/notifications/index.tsx +++ b/src/views/notifications/index.tsx @@ -67,7 +67,7 @@ const NotificationsTimeline = memo( const cacheKey = useTimelineLocationCacheKey(); 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); // measure and cache the hight of every entry @@ -115,13 +115,14 @@ const NotificationsTimeline = memo( items.push(); } + const visible = event.created_at <= dates.max && event.created_at >= dates.min; ids.push(event.id); items.push( = dates.min} - minHeight={numberCache.get(getEventUID(event)) + "px"} + visible={visible} + minHeight={visible ? undefined : numberCache.get(getEventUID(event)) + "px"} />, ); }