···8import {msg} from '@lingui/macro'
9import {useLingui} from '@lingui/react'
10011import {usePalette} from '#/lib/hooks/usePalette'
012import {cleanError} from '#/lib/strings/errors'
013import {logger} from '#/logger'
14import {useModerationOpts} from '#/state/preferences/moderation-opts'
15import {useNotificationFeedQuery} from '#/state/queries/notifications/feed'
16import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread'
17-import {s} from 'lib/styles'
18-import {EmptyState} from '../util/EmptyState'
19-import {ErrorMessage} from '../util/error/ErrorMessage'
20-import {List, ListRef} from '../util/List'
21-import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
22-import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
23-import {CenteredView} from '../util/Views'
24import {FeedItem} from './FeedItem'
25import hairlineWidth = StyleSheet.hairlineWidth
26-import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
27-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
2829const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
30const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
···8import {msg} from '@lingui/macro'
9import {useLingui} from '@lingui/react'
1011+import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
12import {usePalette} from '#/lib/hooks/usePalette'
13+import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
14import {cleanError} from '#/lib/strings/errors'
15+import {s} from '#/lib/styles'
16import {logger} from '#/logger'
17import {useModerationOpts} from '#/state/preferences/moderation-opts'
18import {useNotificationFeedQuery} from '#/state/queries/notifications/feed'
19import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread'
20+import {EmptyState} from '#/view/com/util/EmptyState'
21+import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
22+import {List, ListRef} from '#/view/com/util/List'
23+import {NotificationFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
24+import {LoadMoreRetryBtn} from '#/view/com/util/LoadMoreRetryBtn'
25+import {CenteredView} from '#/view/com/util/Views'
026import {FeedItem} from './FeedItem'
27import hairlineWidth = StyleSheet.hairlineWidth
002829const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
30const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
+27-38
src/view/com/notifications/FeedItem.tsx
···17 ModerationOpts,
18} from '@atproto/api'
19import {AtUri} from '@atproto/api'
20-import {
21- FontAwesomeIcon,
22- FontAwesomeIconStyle,
23- Props,
24-} from '@fortawesome/react-native-fontawesome'
25import {msg, plural, Trans} from '@lingui/macro'
26import {useLingui} from '@lingui/react'
27import {useQueryClient} from '@tanstack/react-query'
···29import {FeedNotification} from '#/state/queries/notifications/feed'
30import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
31import {usePalette} from 'lib/hooks/usePalette'
32-import {HeartIconSolid} from 'lib/icons'
33import {makeProfileLink} from 'lib/routes/links'
34import {sanitizeDisplayName} from 'lib/strings/display-names'
35import {sanitizeHandle} from 'lib/strings/handles'
···37import {colors, s} from 'lib/styles'
38import {isWeb} from 'platform/detection'
39import {precacheProfile} from 'state/queries/profile'
0000000040import {Link as NewLink} from '#/components/Link'
41import {ProfileHoverCard} from '#/components/ProfileHoverCard'
42import {FeedSourceCard} from '../feeds/FeedSourceCard'
···47import {Text} from '../util/text/Text'
48import {TimeElapsed} from '../util/TimeElapsed'
49import {PreviewableUserAvatar, UserAvatar} from '../util/UserAvatar'
050import hairlineWidth = StyleSheet.hairlineWidth
5152const MAX_AUTHORS = 5
···71 const queryClient = useQueryClient()
72 const pal = usePalette('default')
73 const {_} = useLingui()
074 const [isAuthorsExpanded, setAuthorsExpanded] = useState<boolean>(false)
75 const itemHref = useMemo(() => {
76 if (item.type === 'post-like' || item.type === 'repost') {
···150 }
151152 let action = ''
153- let icon: Props['icon'] | 'HeartIconSolid'
154- let iconStyle: Props['style'] = []
0000000155 if (item.type === 'post-like') {
156 action = _(msg`liked your post`)
157- icon = 'HeartIconSolid'
158- iconStyle = [
159- s.likeColor as FontAwesomeIconStyle,
160- {position: 'relative', top: -4},
161- ]
162 } else if (item.type === 'repost') {
163 action = _(msg`reposted your post`)
164- icon = 'retweet'
165- iconStyle = [s.green3 as FontAwesomeIconStyle]
166 } else if (item.type === 'follow') {
167 action = _(msg`followed you`)
168- icon = 'user-plus'
169- iconStyle = [s.blue3 as FontAwesomeIconStyle]
170 } else if (item.type === 'feedgen-like') {
171 action = _(msg`liked your custom feed`)
172- icon = 'HeartIconSolid'
173- iconStyle = [
174- s.likeColor as FontAwesomeIconStyle,
175- {position: 'relative', top: -4},
176- ]
177 } else {
178 return null
179 }
···200 item.type === 'repost'
201 }
202 onBeforePress={onBeforePress}>
203- <View style={styles.layoutIcon}>
204 {/* TODO: Prevent conditional rendering and move toward composable
205 notifications for clearer accessibility labeling */}
206- {icon === 'HeartIconSolid' ? (
207- <HeartIconSolid size={28} style={[styles.icon, ...iconStyle]} />
208- ) : (
209- <FontAwesomeIcon
210- icon={icon}
211- size={24}
212- style={[styles.icon, ...iconStyle]}
213- />
214- )}
215 </View>
216 <View style={styles.layoutContent}>
217 <ExpandListPressable
···322 accessibilityHint={_(
323 msg`Collapses list of users for a given notification`,
324 )}>
325- <FontAwesomeIcon
326- icon="angle-up"
327- size={18}
328 style={[styles.expandedAuthorsCloseBtnIcon, pal.text]}
329 />
330 <Text type="sm-medium" style={pal.text}>
···369 +{authors.length - MAX_AUTHORS}
370 </Text>
371 ) : undefined}
372- <FontAwesomeIcon
373- icon="angle-down"
374- size={18}
375 style={[styles.expandedAuthorsCloseBtnIcon, pal.textLight]}
376 />
377 </View>
···17 ModerationOpts,
18} from '@atproto/api'
19import {AtUri} from '@atproto/api'
0000020import {msg, plural, Trans} from '@lingui/macro'
21import {useLingui} from '@lingui/react'
22import {useQueryClient} from '@tanstack/react-query'
···24import {FeedNotification} from '#/state/queries/notifications/feed'
25import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
26import {usePalette} from 'lib/hooks/usePalette'
027import {makeProfileLink} from 'lib/routes/links'
28import {sanitizeDisplayName} from 'lib/strings/display-names'
29import {sanitizeHandle} from 'lib/strings/handles'
···31import {colors, s} from 'lib/styles'
32import {isWeb} from 'platform/detection'
33import {precacheProfile} from 'state/queries/profile'
34+import {atoms as a, useTheme} from '#/alf'
35+import {
36+ ChevronBottom_Stroke2_Corner0_Rounded as ChevronDownIcon,
37+ ChevronTop_Stroke2_Corner0_Rounded as ChevronUpIcon,
38+} from '#/components/icons/Chevron'
39+import {Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled} from '#/components/icons/Heart2'
40+import {PersonPlus_Filled_Stroke2_Corner0_Rounded as PersonPlusIcon} from '#/components/icons/Person'
41+import {Repost_Stroke2_Corner2_Rounded as RepostIcon} from '#/components/icons/Repost'
42import {Link as NewLink} from '#/components/Link'
43import {ProfileHoverCard} from '#/components/ProfileHoverCard'
44import {FeedSourceCard} from '../feeds/FeedSourceCard'
···49import {Text} from '../util/text/Text'
50import {TimeElapsed} from '../util/TimeElapsed'
51import {PreviewableUserAvatar, UserAvatar} from '../util/UserAvatar'
52+53import hairlineWidth = StyleSheet.hairlineWidth
5455const MAX_AUTHORS = 5
···74 const queryClient = useQueryClient()
75 const pal = usePalette('default')
76 const {_} = useLingui()
77+ const t = useTheme()
78 const [isAuthorsExpanded, setAuthorsExpanded] = useState<boolean>(false)
79 const itemHref = useMemo(() => {
80 if (item.type === 'post-like' || item.type === 'repost') {
···154 }
155156 let action = ''
157+ let icon = (
158+ <HeartIconFilled
159+ size="xl"
160+ style={[
161+ s.likeColor,
162+ // {position: 'relative', top: -4}
163+ ]}
164+ />
165+ )
166 if (item.type === 'post-like') {
167 action = _(msg`liked your post`)
00000168 } else if (item.type === 'repost') {
169 action = _(msg`reposted your post`)
170+ icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} />
0171 } else if (item.type === 'follow') {
172 action = _(msg`followed you`)
173+ icon = <PersonPlusIcon size="xl" style={{color: t.palette.primary_500}} />
0174 } else if (item.type === 'feedgen-like') {
175 action = _(msg`liked your custom feed`)
00000176 } else {
177 return null
178 }
···199 item.type === 'repost'
200 }
201 onBeforePress={onBeforePress}>
202+ <View style={[styles.layoutIcon, a.pr_sm]}>
203 {/* TODO: Prevent conditional rendering and move toward composable
204 notifications for clearer accessibility labeling */}
205+ {icon}
00000000206 </View>
207 <View style={styles.layoutContent}>
208 <ExpandListPressable
···313 accessibilityHint={_(
314 msg`Collapses list of users for a given notification`,
315 )}>
316+ <ChevronUpIcon
317+ size="md"
0318 style={[styles.expandedAuthorsCloseBtnIcon, pal.text]}
319 />
320 <Text type="sm-medium" style={pal.text}>
···359 +{authors.length - MAX_AUTHORS}
360 </Text>
361 ) : undefined}
362+ <ChevronDownIcon
363+ size="md"
0364 style={[styles.expandedAuthorsCloseBtnIcon, pal.textLight]}
365 />
366 </View>
+10-8
src/view/com/util/LoadingPlaceholder.tsx
···8} from 'react-native'
910import {usePalette} from 'lib/hooks/usePalette'
11-import {HeartIconSolid} from 'lib/icons'
12import {s} from 'lib/styles'
13import {useTheme} from 'lib/ThemeContext'
14-import {useTheme as useTheme_NEW} from '#/alf'
15import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
16-import {Heart2_Stroke2_Corner0_Rounded as HeartIconOutline} from '#/components/icons/Heart2'
00017import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost'
18import hairlineWidth = StyleSheet.hairlineWidth
19···139 const pal = usePalette('default')
140 return (
141 <View style={[styles.notification, pal.view, style]}>
142- <View style={{paddingLeft: 30, paddingRight: 10}}>
143- <HeartIconSolid
144- style={{color: pal.colors.backgroundLight} as ViewStyle}
145- size={30}
146 />
147 </View>
148 <View style={{flex: 1}}>
149- <View style={[s.flexRow, s.mb10]}>
150 <LoadingPlaceholder
151 width={30}
152 height={30}
···8} from 'react-native'
910import {usePalette} from 'lib/hooks/usePalette'
011import {s} from 'lib/styles'
12import {useTheme} from 'lib/ThemeContext'
13+import {atoms as a, useTheme as useTheme_NEW} from '#/alf'
14import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
15+import {
16+ Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled,
17+ Heart2_Stroke2_Corner0_Rounded as HeartIconOutline,
18+} from '#/components/icons/Heart2'
19import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost'
20import hairlineWidth = StyleSheet.hairlineWidth
21···141 const pal = usePalette('default')
142 return (
143 <View style={[styles.notification, pal.view, style]}>
144+ <View style={[{width: 70}, a.align_end, a.pr_sm, a.pt_2xs]}>
145+ <HeartIconFilled
146+ size="xl"
147+ style={{color: pal.colors.backgroundLight}}
148 />
149 </View>
150 <View style={{flex: 1}}>
151+ <View style={[a.flex_row, s.mb10]}>
152 <LoadingPlaceholder
153 width={30}
154 height={30}