mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at verify-code 8.4 kB view raw
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})