mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {View} from 'react-native'
3import {AtUri} from '@atproto/api'
4import {msg} from '@lingui/macro'
5import {useLingui} from '@lingui/react'
6
7import {PressableScale} from '#/lib/custom-animations/PressableScale'
8// import {makeProfileLink} from '#/lib/routes/links'
9// import {feedUriToHref} from '#/lib/strings/url-helpers'
10// import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
11// import {CloseQuote_Filled_Stroke2_Corner0_Rounded as Quote} from '#/components/icons/Quote'
12// import {UserAvatar} from '#/view/com/util/UserAvatar'
13import type {TrendingTopic} from '#/state/queries/trending/useTrendingTopics'
14import {atoms as a, native, useTheme, ViewStyleProp} from '#/alf'
15import {StarterPack as StarterPackIcon} from '#/components/icons/StarterPack'
16import {Link as InternalLink, LinkProps} from '#/components/Link'
17import {Text} from '#/components/Typography'
18
19export function TrendingTopic({
20 topic: raw,
21 size,
22 style,
23}: {topic: TrendingTopic; size?: 'large' | 'small'} & ViewStyleProp) {
24 const t = useTheme()
25 const topic = useTopic(raw)
26
27 const isSmall = size === 'small'
28 const hasIcon = topic.type === 'starter-pack' && !isSmall
29 const iconSize = 20
30
31 return (
32 <View
33 style={[
34 a.flex_row,
35 a.align_center,
36 a.rounded_full,
37 a.border,
38 t.atoms.border_contrast_medium,
39 t.atoms.bg,
40 isSmall
41 ? [
42 {
43 paddingVertical: 5,
44 paddingHorizontal: 10,
45 },
46 ]
47 : [a.py_sm, a.px_md],
48 hasIcon && {gap: 6},
49 style,
50 ]}>
51 {hasIcon && topic.type === 'starter-pack' && (
52 <StarterPackIcon
53 gradient="sky"
54 width={iconSize}
55 style={{marginLeft: -3, marginVertical: -1}}
56 />
57 )}
58
59 {/*
60 <View
61 style={[
62 a.align_center,
63 a.justify_center,
64 a.rounded_full,
65 a.overflow_hidden,
66 {
67 width: iconSize,
68 height: iconSize,
69 },
70 ]}>
71 {topic.type === 'tag' ? (
72 <Hashtag width={iconSize} />
73 ) : topic.type === 'topic' ? (
74 <Quote width={iconSize - 2} />
75 ) : topic.type === 'feed' ? (
76 <UserAvatar
77 type="user"
78 size={aviSize}
79 avatar=""
80 />
81 ) : (
82 <UserAvatar
83 type="user"
84 size={aviSize}
85 avatar=""
86 />
87 )}
88 </View>
89 */}
90
91 <Text
92 style={[
93 a.font_bold,
94 a.leading_tight,
95 isSmall ? [a.text_sm] : [a.text_md, {paddingBottom: 1}],
96 ]}
97 numberOfLines={1}>
98 {topic.displayName}
99 </Text>
100 </View>
101 )
102}
103
104export function TrendingTopicSkeleton({
105 size = 'large',
106 index = 0,
107}: {
108 size?: 'large' | 'small'
109 index?: number
110}) {
111 const t = useTheme()
112 const isSmall = size === 'small'
113 return (
114 <View
115 style={[
116 a.rounded_full,
117 a.border,
118 t.atoms.border_contrast_medium,
119 t.atoms.bg_contrast_25,
120 isSmall
121 ? {
122 width: index % 2 === 0 ? 75 : 90,
123 height: 27,
124 }
125 : {
126 width: index % 2 === 0 ? 90 : 110,
127 height: 36,
128 },
129 ]}
130 />
131 )
132}
133
134export function TrendingTopicLink({
135 topic: raw,
136 children,
137 ...rest
138}: {
139 topic: TrendingTopic
140} & Omit<LinkProps, 'to' | 'label'>) {
141 const topic = useTopic(raw)
142
143 return (
144 <InternalLink
145 label={topic.label}
146 to={topic.url}
147 PressableComponent={native(PressableScale)}
148 {...rest}>
149 {children}
150 </InternalLink>
151 )
152}
153
154type ParsedTrendingTopic =
155 | {
156 type: 'topic' | 'tag' | 'starter-pack' | 'unknown'
157 label: string
158 displayName: string
159 url: string
160 uri: undefined
161 }
162 | {
163 type: 'profile' | 'feed'
164 label: string
165 displayName: string
166 url: string
167 uri: AtUri
168 }
169
170export function useTopic(raw: TrendingTopic): ParsedTrendingTopic {
171 const {_} = useLingui()
172 return React.useMemo(() => {
173 const {topic: displayName, link} = raw
174
175 if (link.startsWith('/search')) {
176 return {
177 type: 'topic',
178 label: _(msg`Browse posts about ${displayName}`),
179 displayName,
180 uri: undefined,
181 url: link,
182 }
183 } else if (link.startsWith('/hashtag')) {
184 return {
185 type: 'tag',
186 label: _(msg`Browse posts tagged with ${displayName}`),
187 displayName,
188 // displayName: displayName.replace(/^#/, ''),
189 uri: undefined,
190 url: link,
191 }
192 } else if (link.startsWith('/starter-pack')) {
193 return {
194 type: 'starter-pack',
195 label: _(msg`Browse starter pack ${displayName}`),
196 displayName,
197 uri: undefined,
198 url: link,
199 }
200 }
201
202 /*
203 if (!link.startsWith('at://')) {
204 // above logic
205 } else {
206 const urip = new AtUri(link)
207 switch (urip.collection) {
208 case 'app.bsky.actor.profile': {
209 return {
210 type: 'profile',
211 label: _(msg`View ${displayName}'s profile`),
212 displayName,
213 uri: urip,
214 url: makeProfileLink({did: urip.host, handle: urip.host}),
215 }
216 }
217 case 'app.bsky.feed.generator': {
218 return {
219 type: 'feed',
220 label: _(msg`Browse the ${displayName} feed`),
221 displayName,
222 uri: urip,
223 url: feedUriToHref(link),
224 }
225 }
226 }
227 }
228 */
229
230 return {
231 type: 'unknown',
232 label: _(msg`Browse topic ${displayName}`),
233 displayName,
234 uri: undefined,
235 url: link,
236 }
237 }, [_, raw])
238}