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