forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {View} from 'react-native'
2import {msg, Trans} from '@lingui/macro'
3import {useLingui} from '@lingui/react'
4
5import {
6 useTrendingSettings,
7 useTrendingSettingsApi,
8} from '#/state/preferences/trending'
9import {useTrendingTopics} from '#/state/queries/trending/useTrendingTopics'
10import {useTrendingConfig} from '#/state/service-config'
11import {atoms as a, useTheme} from '#/alf'
12import {Button, ButtonIcon} from '#/components/Button'
13import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
14import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/icons/Trending'
15import * as Prompt from '#/components/Prompt'
16import {TrendingTopicLink} from '#/components/TrendingTopics'
17import {Text} from '#/components/Typography'
18import {useAnalytics} from '#/analytics'
19
20const TRENDING_LIMIT = 5
21
22export function SidebarTrendingTopics() {
23 const {enabled} = useTrendingConfig()
24 const {trendingDisabled} = useTrendingSettings()
25 return !enabled ? null : trendingDisabled ? null : <Inner />
26}
27
28function Inner() {
29 const t = useTheme()
30 const {_} = useLingui()
31 const ax = useAnalytics()
32 const trendingPrompt = Prompt.usePromptControl()
33 const {setTrendingDisabled} = useTrendingSettingsApi()
34 const {data: trending, error, isLoading} = useTrendingTopics()
35 const noTopics = !isLoading && !error && !trending?.topics?.length
36
37 const onConfirmHide = () => {
38 ax.metric('trendingTopics:hide', {context: 'sidebar'})
39 setTrendingDisabled(true)
40 }
41
42 return error || noTopics ? null : (
43 <>
44 <View
45 style={[a.p_lg, a.rounded_md, a.border, t.atoms.border_contrast_low]}>
46 <View style={[a.flex_row, a.align_center, a.gap_xs, a.pb_md]}>
47 <TrendingIcon width={16} height={16} fill={t.atoms.text.color} />
48 <Text style={[a.flex_1, a.text_md, a.font_semi_bold, t.atoms.text]}>
49 <Trans>Trending</Trans>
50 </Text>
51 <Button
52 variant="ghost"
53 size="tiny"
54 color="secondary"
55 shape="round"
56 label={_(msg`Trending options`)}
57 onPress={() => trendingPrompt.open()}
58 style={[a.bg_transparent, {marginTop: -6, marginRight: -6}]}>
59 <ButtonIcon icon={Ellipsis} size="xs" />
60 </Button>
61 </View>
62
63 <View style={[a.gap_xs]}>
64 {isLoading ? (
65 Array(TRENDING_LIMIT)
66 .fill(0)
67 .map((_n, i) => (
68 <View key={i} style={[a.flex_row, a.align_center, a.gap_sm]}>
69 <Text
70 style={[
71 a.text_sm,
72 t.atoms.text_contrast_low,
73 {minWidth: 16},
74 ]}>
75 {i + 1}.
76 </Text>
77 <View
78 style={[
79 a.rounded_xs,
80 t.atoms.bg_contrast_50,
81 {height: 14, width: i % 2 === 0 ? 80 : 100},
82 ]}
83 />
84 </View>
85 ))
86 ) : !trending?.topics ? null : (
87 <>
88 {trending.topics.slice(0, TRENDING_LIMIT).map((topic, i) => (
89 <TrendingTopicLink
90 key={topic.link}
91 topic={topic}
92 style={[a.self_start]}
93 onPress={() => {
94 ax.metric('trendingTopic:click', {context: 'sidebar'})
95 }}>
96 {({hovered}) => (
97 <View style={[a.flex_row, a.align_center, a.gap_xs]}>
98 <Text
99 style={[
100 a.text_sm,
101 a.leading_snug,
102 t.atoms.text_contrast_low,
103 {minWidth: 16},
104 ]}>
105 {i + 1}.
106 </Text>
107 <Text
108 style={[
109 a.text_sm,
110 a.leading_snug,
111 hovered
112 ? [t.atoms.text, a.underline]
113 : t.atoms.text_contrast_medium,
114 ]}
115 numberOfLines={1}>
116 {topic.displayName ?? topic.topic}
117 </Text>
118 </View>
119 )}
120 </TrendingTopicLink>
121 ))}
122 </>
123 )}
124 </View>
125 </View>
126 <Prompt.Basic
127 control={trendingPrompt}
128 title={_(msg`Hide trending topics?`)}
129 description={_(msg`You can update this later from your settings.`)}
130 confirmButtonCta={_(msg`Hide`)}
131 onConfirm={onConfirmHide}
132 />
133 </>
134 )
135}