mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at update-sentry 161 lines 3.7 kB view raw
1import React from 'react' 2import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' 3import {Image} from 'expo-image' 4import {AppBskyFeedDefs} from '@atproto/api' 5import {Trans} from '@lingui/macro' 6 7import {isTenorGifUri} from '#/lib/strings/embed-player' 8import {atoms as a, useTheme} from '#/alf' 9import {MediaInsetBorder} from '#/components/MediaInsetBorder' 10import {Text} from '#/components/Typography' 11import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' 12import * as bsky from '#/types/bsky' 13 14/** 15 * Streamlined MediaPreview component which just handles images, gifs, and videos 16 */ 17export function Embed({ 18 embed, 19 style, 20}: { 21 embed: AppBskyFeedDefs.PostView['embed'] 22 style?: StyleProp<ViewStyle> 23}) { 24 const e = bsky.post.parseEmbed(embed) 25 26 if (!e) return null 27 28 if (e.type === 'images') { 29 return ( 30 <Outer style={style}> 31 {e.view.images.map(image => ( 32 <ImageItem 33 key={image.thumb} 34 thumbnail={image.thumb} 35 alt={image.alt} 36 /> 37 ))} 38 </Outer> 39 ) 40 } else if (e.type === 'link') { 41 if (!e.view.external.thumb) return null 42 if (!isTenorGifUri(e.view.external.uri)) return null 43 return ( 44 <Outer style={style}> 45 <GifItem 46 thumbnail={e.view.external.thumb} 47 alt={e.view.external.title} 48 /> 49 </Outer> 50 ) 51 } else if (e.type === 'video') { 52 return ( 53 <Outer style={style}> 54 <VideoItem thumbnail={e.view.thumbnail} alt={e.view.alt} /> 55 </Outer> 56 ) 57 } 58 59 return null 60} 61 62export function Outer({ 63 children, 64 style, 65}: { 66 children?: React.ReactNode 67 style?: StyleProp<ViewStyle> 68}) { 69 return <View style={[a.flex_row, a.gap_xs, style]}>{children}</View> 70} 71 72export function ImageItem({ 73 thumbnail, 74 alt, 75 children, 76}: { 77 thumbnail: string 78 alt?: string 79 children?: React.ReactNode 80}) { 81 const t = useTheme() 82 return ( 83 <View style={[a.relative, a.flex_1, {aspectRatio: 1, maxWidth: 100}]}> 84 <Image 85 key={thumbnail} 86 source={{uri: thumbnail}} 87 style={[a.flex_1, a.rounded_xs, t.atoms.bg_contrast_25]} 88 contentFit="cover" 89 accessible={true} 90 accessibilityIgnoresInvertColors 91 accessibilityHint={alt} 92 accessibilityLabel="" 93 /> 94 <MediaInsetBorder style={[a.rounded_xs]} /> 95 {children} 96 </View> 97 ) 98} 99 100export function GifItem({thumbnail, alt}: {thumbnail: string; alt?: string}) { 101 return ( 102 <ImageItem thumbnail={thumbnail} alt={alt}> 103 <View style={[a.absolute, a.inset_0, a.justify_center, a.align_center]}> 104 <PlayButtonIcon size={24} /> 105 </View> 106 <View style={styles.altContainer}> 107 <Text style={styles.alt}> 108 <Trans>GIF</Trans> 109 </Text> 110 </View> 111 </ImageItem> 112 ) 113} 114 115export function VideoItem({ 116 thumbnail, 117 alt, 118}: { 119 thumbnail?: string 120 alt?: string 121}) { 122 if (!thumbnail) { 123 return ( 124 <View 125 style={[ 126 {backgroundColor: 'black'}, 127 a.flex_1, 128 {aspectRatio: 1, maxWidth: 100}, 129 a.justify_center, 130 a.align_center, 131 ]}> 132 <PlayButtonIcon size={24} /> 133 </View> 134 ) 135 } 136 return ( 137 <ImageItem thumbnail={thumbnail} alt={alt}> 138 <View style={[a.absolute, a.inset_0, a.justify_center, a.align_center]}> 139 <PlayButtonIcon size={24} /> 140 </View> 141 </ImageItem> 142 ) 143} 144 145const styles = StyleSheet.create({ 146 altContainer: { 147 backgroundColor: 'rgba(0, 0, 0, 0.75)', 148 borderRadius: 6, 149 paddingHorizontal: 6, 150 paddingVertical: 3, 151 position: 'absolute', 152 right: 5, 153 bottom: 5, 154 zIndex: 2, 155 }, 156 alt: { 157 color: 'white', 158 fontSize: 7, 159 fontWeight: '600', 160 }, 161})