mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {
3 DimensionValue,
4 StyleProp,
5 StyleSheet,
6 View,
7 ViewStyle,
8} from 'react-native'
9
10import {usePalette} from 'lib/hooks/usePalette'
11import {s} from 'lib/styles'
12import {useTheme} from 'lib/ThemeContext'
13import {atoms as a, useTheme as useTheme_NEW} from '#/alf'
14import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
15import {
16 Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled,
17 Heart2_Stroke2_Corner0_Rounded as HeartIconOutline,
18} from '#/components/icons/Heart2'
19import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost'
20
21export function LoadingPlaceholder({
22 width,
23 height,
24 style,
25}: {
26 width: DimensionValue
27 height: DimensionValue
28 style?: StyleProp<ViewStyle>
29}) {
30 const theme = useTheme()
31 return (
32 <View
33 style={[
34 styles.loadingPlaceholder,
35 {
36 width,
37 height,
38 backgroundColor: theme.palette.default.backgroundLight,
39 },
40 style,
41 ]}
42 />
43 )
44}
45
46export function PostLoadingPlaceholder({
47 style,
48}: {
49 style?: StyleProp<ViewStyle>
50}) {
51 const t = useTheme_NEW()
52 const pal = usePalette('default')
53 return (
54 <View style={[styles.post, pal.view, style]}>
55 <LoadingPlaceholder
56 width={52}
57 height={52}
58 style={[
59 styles.avatar,
60 {
61 position: 'relative',
62 top: -6,
63 },
64 ]}
65 />
66 <View style={[s.flex1]}>
67 <LoadingPlaceholder width={100} height={6} style={{marginBottom: 10}} />
68 <LoadingPlaceholder width="95%" height={6} style={{marginBottom: 8}} />
69 <LoadingPlaceholder width="95%" height={6} style={{marginBottom: 8}} />
70 <LoadingPlaceholder width="80%" height={6} style={{marginBottom: 11}} />
71 <View style={styles.postCtrls}>
72 <View style={[styles.postCtrl, {marginLeft: -6}]}>
73 <View style={styles.postBtn}>
74 <Bubble
75 style={[
76 {
77 color: t.palette.contrast_500,
78 },
79 {pointerEvents: 'none'},
80 ]}
81 width={18}
82 />
83 </View>
84 </View>
85 <View style={styles.postCtrl}>
86 <View style={styles.postBtn}>
87 <Repost
88 style={[
89 {
90 color: t.palette.contrast_500,
91 },
92 {pointerEvents: 'none'},
93 ]}
94 width={18}
95 />
96 </View>
97 </View>
98 <View style={styles.postCtrl}>
99 <View style={styles.postBtn}>
100 <HeartIconOutline
101 style={[
102 {
103 color: t.palette.contrast_500,
104 },
105 {pointerEvents: 'none'},
106 ]}
107 width={18}
108 />
109 </View>
110 </View>
111 <View style={styles.postCtrl}>
112 <View style={[styles.postBtn, {minHeight: 30}]} />
113 </View>
114 </View>
115 </View>
116 </View>
117 )
118}
119
120export function PostFeedLoadingPlaceholder() {
121 return (
122 <View>
123 <PostLoadingPlaceholder />
124 <PostLoadingPlaceholder />
125 <PostLoadingPlaceholder />
126 <PostLoadingPlaceholder />
127 <PostLoadingPlaceholder />
128 <PostLoadingPlaceholder />
129 <PostLoadingPlaceholder />
130 <PostLoadingPlaceholder />
131 </View>
132 )
133}
134
135export function NotificationLoadingPlaceholder({
136 style,
137}: {
138 style?: StyleProp<ViewStyle>
139}) {
140 const pal = usePalette('default')
141 return (
142 <View style={[styles.notification, pal.view, style]}>
143 <View style={[{width: 70}, a.align_end, a.pr_sm, a.pt_2xs]}>
144 <HeartIconFilled
145 size="xl"
146 style={{color: pal.colors.backgroundLight}}
147 />
148 </View>
149 <View style={{flex: 1}}>
150 <View style={[a.flex_row, s.mb10]}>
151 <LoadingPlaceholder
152 width={30}
153 height={30}
154 style={styles.smallAvatar}
155 />
156 </View>
157 <LoadingPlaceholder width="90%" height={6} style={[s.mb5]} />
158 <LoadingPlaceholder width="70%" height={6} style={[s.mb5]} />
159 </View>
160 </View>
161 )
162}
163
164export function NotificationFeedLoadingPlaceholder() {
165 return (
166 <>
167 <NotificationLoadingPlaceholder />
168 <NotificationLoadingPlaceholder />
169 <NotificationLoadingPlaceholder />
170 <NotificationLoadingPlaceholder />
171 <NotificationLoadingPlaceholder />
172 <NotificationLoadingPlaceholder />
173 <NotificationLoadingPlaceholder />
174 <NotificationLoadingPlaceholder />
175 <NotificationLoadingPlaceholder />
176 <NotificationLoadingPlaceholder />
177 <NotificationLoadingPlaceholder />
178 </>
179 )
180}
181
182export function ProfileCardLoadingPlaceholder({
183 style,
184}: {
185 style?: StyleProp<ViewStyle>
186}) {
187 const pal = usePalette('default')
188 return (
189 <View style={[styles.profileCard, pal.view, style]}>
190 <LoadingPlaceholder
191 width={40}
192 height={40}
193 style={styles.profileCardAvi}
194 />
195 <View>
196 <LoadingPlaceholder width={140} height={8} style={[s.mb5]} />
197 <LoadingPlaceholder width={120} height={8} style={[s.mb10]} />
198 <LoadingPlaceholder width={220} height={8} style={[s.mb5]} />
199 </View>
200 </View>
201 )
202}
203
204export function ProfileCardFeedLoadingPlaceholder() {
205 return (
206 <>
207 <ProfileCardLoadingPlaceholder />
208 <ProfileCardLoadingPlaceholder />
209 <ProfileCardLoadingPlaceholder />
210 <ProfileCardLoadingPlaceholder />
211 <ProfileCardLoadingPlaceholder />
212 <ProfileCardLoadingPlaceholder />
213 <ProfileCardLoadingPlaceholder />
214 <ProfileCardLoadingPlaceholder />
215 <ProfileCardLoadingPlaceholder />
216 <ProfileCardLoadingPlaceholder />
217 <ProfileCardLoadingPlaceholder />
218 </>
219 )
220}
221
222export function FeedLoadingPlaceholder({
223 style,
224 showLowerPlaceholder = true,
225 showTopBorder = true,
226}: {
227 style?: StyleProp<ViewStyle>
228 showTopBorder?: boolean
229 showLowerPlaceholder?: boolean
230}) {
231 const pal = usePalette('default')
232 return (
233 <View
234 style={[
235 {
236 paddingHorizontal: 12,
237 paddingVertical: 18,
238 borderTopWidth: showTopBorder ? StyleSheet.hairlineWidth : 0,
239 },
240 pal.border,
241 style,
242 ]}>
243 <View style={[pal.view, {flexDirection: 'row'}]}>
244 <LoadingPlaceholder
245 width={36}
246 height={36}
247 style={[styles.avatar, {borderRadius: 6}]}
248 />
249 <View style={[s.flex1]}>
250 <LoadingPlaceholder width={100} height={8} style={[s.mt5, s.mb10]} />
251 <LoadingPlaceholder width={120} height={8} />
252 </View>
253 </View>
254 {showLowerPlaceholder && (
255 <View style={{paddingHorizontal: 5, marginTop: 10}}>
256 <LoadingPlaceholder
257 width={260}
258 height={8}
259 style={{marginVertical: 12}}
260 />
261 <LoadingPlaceholder width={120} height={8} />
262 </View>
263 )}
264 </View>
265 )
266}
267
268export function FeedFeedLoadingPlaceholder() {
269 return (
270 <>
271 <FeedLoadingPlaceholder />
272 <FeedLoadingPlaceholder />
273 <FeedLoadingPlaceholder />
274 <FeedLoadingPlaceholder />
275 <FeedLoadingPlaceholder />
276 <FeedLoadingPlaceholder />
277 <FeedLoadingPlaceholder />
278 <FeedLoadingPlaceholder />
279 <FeedLoadingPlaceholder />
280 <FeedLoadingPlaceholder />
281 <FeedLoadingPlaceholder />
282 </>
283 )
284}
285
286const styles = StyleSheet.create({
287 loadingPlaceholder: {
288 borderRadius: 6,
289 },
290 post: {
291 flexDirection: 'row',
292 alignItems: 'flex-start',
293 paddingHorizontal: 10,
294 paddingTop: 20,
295 paddingBottom: 5,
296 paddingRight: 15,
297 },
298 postCtrls: {
299 opacity: 0.5,
300 flexDirection: 'row',
301 justifyContent: 'space-between',
302 },
303 postCtrl: {
304 flex: 1,
305 },
306 postBtn: {
307 flex: 1,
308 flexDirection: 'row',
309 alignItems: 'center',
310 padding: 5,
311 },
312 avatar: {
313 borderRadius: 26,
314 marginRight: 10,
315 marginLeft: 8,
316 },
317 notification: {
318 flexDirection: 'row',
319 padding: 10,
320 },
321 profileCard: {
322 flexDirection: 'row',
323 padding: 10,
324 margin: 1,
325 },
326 profileCardAvi: {
327 borderRadius: 20,
328 marginRight: 10,
329 },
330 smallAvatar: {
331 borderRadius: 15,
332 marginRight: 10,
333 },
334})