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