forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {View} from 'react-native'
2import {type AppBskyUnspeccedDefs} from '@atproto/api'
3import {Trans} from '@lingui/react/macro'
4
5import {
6 DEFAULT_LIMIT as RECOMMENDATIONS_COUNT,
7 useTrendingTopics,
8} from '#/state/queries/trending/useTrendingTopics'
9import {useTrendingConfig} from '#/state/service-config'
10import {atoms as a, useGutters, useTheme} from '#/alf'
11import {Hashtag_Stroke2_Corner0_Rounded} from '#/components/icons/Hashtag'
12import {
13 TrendingTopic,
14 TrendingTopicLink,
15 TrendingTopicSkeleton,
16} from '#/components/TrendingTopics'
17import {Text} from '#/components/Typography'
18import {useAnalytics} from '#/analytics'
19import {IS_WEB} from '#/env'
20
21// Note: This module is not currently used and may be removed in the future.
22
23export function ExploreRecommendations() {
24 const {enabled} = useTrendingConfig()
25 return enabled ? <Inner /> : null
26}
27
28function Inner() {
29 const t = useTheme()
30 const ax = useAnalytics()
31 const gutters = useGutters([0, 'compact'])
32 const {data: trending, error, isLoading} = useTrendingTopics()
33 const noRecs = !isLoading && !error && !trending?.suggested?.length
34 const allFeeds = trending?.suggested && isAllFeeds(trending.suggested)
35
36 return error || noRecs ? null : (
37 <>
38 <View
39 style={[
40 a.flex_row,
41 IS_WEB
42 ? [a.px_lg, a.py_lg, a.pt_2xl, a.gap_md]
43 : [a.p_lg, a.pt_2xl, a.gap_md],
44 a.border_b,
45 t.atoms.border_contrast_low,
46 ]}>
47 <View style={[a.flex_1, a.gap_sm]}>
48 <View style={[a.flex_row, a.align_center, a.gap_sm]}>
49 <Hashtag_Stroke2_Corner0_Rounded
50 size="lg"
51 fill={t.palette.primary_500}
52 style={{marginLeft: -2}}
53 />
54 <Text style={[a.text_2xl, a.font_bold, t.atoms.text]}>
55 <Trans>Recommended</Trans>
56 </Text>
57 </View>
58 {!allFeeds ? (
59 <Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
60 <Trans>
61 Content from across the network we think you might like.
62 </Trans>
63 </Text>
64 ) : (
65 <Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
66 <Trans>Feeds we think you might like.</Trans>
67 </Text>
68 )}
69 </View>
70 </View>
71
72 <View style={[a.pt_md, a.pb_lg]}>
73 <View
74 style={[
75 a.flex_row,
76 a.justify_start,
77 a.flex_wrap,
78 {rowGap: 8, columnGap: 6},
79 gutters,
80 ]}>
81 {isLoading ? (
82 Array(RECOMMENDATIONS_COUNT)
83 .fill(0)
84 .map((_, i) => <TrendingTopicSkeleton key={i} index={i} />)
85 ) : !trending?.suggested ? null : (
86 <>
87 {trending.suggested.map(topic => (
88 <TrendingTopicLink
89 key={topic.link}
90 topic={topic}
91 onPress={() => {
92 ax.metric('recommendedTopic:click', {context: 'explore'})
93 }}>
94 {({hovered}) => (
95 <TrendingTopic
96 topic={topic}
97 style={[
98 hovered && [
99 t.atoms.border_contrast_high,
100 t.atoms.bg_contrast_25,
101 ],
102 ]}
103 />
104 )}
105 </TrendingTopicLink>
106 ))}
107 </>
108 )}
109 </View>
110 </View>
111 </>
112 )
113}
114
115function isAllFeeds(topics: AppBskyUnspeccedDefs.TrendingTopic[]) {
116 return topics.every(topic => {
117 const segments = topic.link.split('/').slice(1)
118 return segments[0] === 'profile' && segments[2] === 'feed'
119 })
120}