From 32fe96dde33834cc50d5ba5e52017db2208fdaf7 Mon Sep 17 00:00:00 2001 From: "xan.lol" Date: Sun, 31 May 2026 19:15:43 -0700 Subject: [PATCH] fix: PDS badge not visible in notification feed screen & uncollapsing items crashing native UITextView only supports text children so the PDS badge couldn't render. ProfileBadges was mounted for every user when expanding a grouped notification and a delay was necessary to not unmount until that animation finished, to prevent the mobile app from crashing! --- .../notifications/NotificationFeedItem.tsx | 96 ++++++++++++++----- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/src/view/com/notifications/NotificationFeedItem.tsx b/src/view/com/notifications/NotificationFeedItem.tsx index e12e83711..6445e5905 100644 --- a/src/view/com/notifications/NotificationFeedItem.tsx +++ b/src/view/com/notifications/NotificationFeedItem.tsx @@ -1,4 +1,4 @@ -import {memo, useCallback, useEffect, useMemo, useState} from 'react' +import {Children, cloneElement, memo, useCallback, useEffect, useMemo, useState} from 'react' import { Animated, type GestureResponderEvent, @@ -244,30 +244,29 @@ let NotificationFeedItem = ({ const firstAuthorLink = ( - - {forceLTR(firstAuthorName)} + + + {forceLTR(firstAuthorName)} + - + ) const additionalAuthorsCount = authors.length - 1 @@ -649,18 +648,16 @@ let NotificationFeedItem = ({ visible={isAuthorsExpanded} authors={authors} /> - - {notificationContent} + {({timeElapsed}) => ( <> @@ -677,7 +674,7 @@ let NotificationFeedItem = ({ )} - + {(item.type === 'follow' && !hasMultipleAuthors && !isFollowBack) || (item.type === 'contact-match' && @@ -730,6 +727,47 @@ let NotificationFeedItem = ({ NotificationFeedItem = memo(NotificationFeedItem) export {NotificationFeedItem} +function NotificationContent({ + content, +}: { + content: React.ReactElement<{component?: typeof NotificationSentence}> +}) { + return cloneElement(content, {component: NotificationSentence}) +} + +function NotificationSentence({children}: {children: React.ReactNode}) { + const t = useTheme() + return ( + + {renderInlineTransChildren(children, t)} + + ) +} + +function renderInlineTransChildren( + children: React.ReactNode, + t: ReturnType, +): React.ReactNode { + return Children.map(children, (child, i) => { + if (typeof child === 'string') { + if (!child) { + return null + } + return ( + + {child} + + ) + } + if (Array.isArray(child)) { + return renderInlineTransChildren(child, t) + } + return child + }) +} + function ExpandListPressable({ hasMultipleAuthors, children, @@ -1040,6 +1078,7 @@ function ExpandedAuthorsList({ authors: Author[] }) { const heightInterp = useAnimatedValue(visible ? 1 : 0) + const [shouldRenderAuthors, setShouldRenderAuthors] = useState(visible) const targetHeight = authors.length * (EXPANDED_AUTHOR_EL_HEIGHT + 10) /*10=margin*/ const heightStyle = { @@ -1052,10 +1091,18 @@ function ExpandedAuthorsList({ useNativeDriver: false, }).start() }, [heightInterp, visible]) + useEffect(() => { + if (visible) { + setShouldRenderAuthors(true) + return + } + const timeout = setTimeout(() => setShouldRenderAuthors(false), 200) + return () => clearTimeout(timeout) + }, [visible]) return ( - {visible && + {shouldRenderAuthors && authors.map(author => ( ))} @@ -1104,6 +1151,7 @@ function ExpandedAuthorCard({author}: {author: Author}) {