diff --git a/src/analytics/features/types.ts b/src/analytics/features/types.ts index 36a354bb49..af046736cf 100644 --- a/src/analytics/features/types.ts +++ b/src/analytics/features/types.ts @@ -15,5 +15,6 @@ export enum Features { DmsNewMessageComposerEnable = 'dms:new_message_composer:enable', KlipyGifProviderEnable = 'klipy_gif_provider:enable', PostGalleryEmbedEnable = 'post_gallery_embed:enable', + NotificationsExpandedProfileCardEnable = 'notifications:expanded_profile_card:enable', AATest = 'aa-test', } diff --git a/src/view/com/notifications/NotificationFeedItem.tsx b/src/view/com/notifications/NotificationFeedItem.tsx index 79a8d746e8..404cda3edb 100644 --- a/src/view/com/notifications/NotificationFeedItem.tsx +++ b/src/view/com/notifications/NotificationFeedItem.tsx @@ -2,6 +2,7 @@ import {memo, useCallback, useEffect, useMemo, useState} from 'react' import { Animated, type GestureResponderEvent, + type LayoutChangeEvent, Pressable, StyleSheet, TouchableOpacity, @@ -63,11 +64,14 @@ import {VerifiedCheck} from '#/components/icons/VerifiedCheck' import {InlineLinkText, Link} from '#/components/Link' import * as MediaPreview from '#/components/MediaPreview' import {ProfileBadges} from '#/components/ProfileBadges' +import * as ProfileCard from '#/components/ProfileCard' import {ProfileHoverCard} from '#/components/ProfileHoverCard' import {Notification as StarterPackCard} from '#/components/StarterPack/StarterPackCard' import {SubtleHover} from '#/components/SubtleHover' import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' +import {useAnalytics} from '#/analytics' +import {IS_WEB} from '#/env' import * as bsky from '#/types/bsky' const MAX_AUTHORS = 5 @@ -616,7 +620,7 @@ let NotificationFeedItem = ({ }}> {({hovered}) => ( <> - + {/* TODO: Prevent conditional rendering and move toward composable notifications for clearer accessibility labeling */} @@ -635,6 +639,7 @@ let NotificationFeedItem = ({ { + Animated.timing(isNativeFade ? opacityInterp : heightInterp, { + toValue: visible ? 1 : 0, + duration: 200, + useNativeDriver: isNativeFade, + }).start() + }, [heightInterp, opacityInterp, visible, isNativeFade]) + const onInnerLayout = (e: LayoutChangeEvent) => { + if (measuredHeight === 0) { + setMeasuredHeight(e.nativeEvent.layout.height) + } + } + + if (isNativeFade) { + return ( + + {visible && ( + + {authors.map((author, i) => ( + + ))} + + )} + + ) + } + + const targetHeight = profileCardEnabled + ? measuredHeight + : authors.length * (EXPANDED_AUTHOR_EL_HEIGHT + 10) /*10=margin*/ const heightStyle = { height: Animated.multiply(heightInterp, targetHeight), } - useEffect(() => { - Animated.timing(heightInterp, { - toValue: visible ? 1 : 0, - duration: 200, - useNativeDriver: false, - }).start() - }, [heightInterp, visible]) - return ( - {visible && + {profileCardEnabled ? ( + + {authors.map((author, i) => ( + + ))} + + ) : ( + visible && authors.map(author => ( - ))} + )) + )} ) } +function ExpandedAuthorProfileCard({ + author, + moderationOpts, + isLast, +}: { + author: Author + moderationOpts: ModerationOpts + isLast: boolean +}) { + return ( + + + + + + + + + + ) +} + function ExpandedAuthorCard({author}: {author: Author}) { const t = useTheme() const {_} = useLingui() return (