Bluesky app fork with some witchin' additions 馃挮
at readme-update 175 lines 4.6 kB view raw
1import React from 'react' 2import {type StyleProp, View, type ViewStyle} from 'react-native' 3 4import {cleanError} from '#/lib/strings/errors' 5import { 6 useResolveGifQuery, 7 useResolveLinkQuery, 8} from '#/state/queries/resolve-link' 9import {type Gif} from '#/state/queries/tenor' 10import {ExternalEmbedRemoveBtn} from '#/view/com/composer/ExternalEmbedRemoveBtn' 11import {atoms as a, useTheme} from '#/alf' 12import {Loader} from '#/components/Loader' 13import {ExternalEmbed} from '#/components/Post/Embed/ExternalEmbed' 14import {ModeratedFeedEmbed} from '#/components/Post/Embed/FeedEmbed' 15import {ModeratedListEmbed} from '#/components/Post/Embed/ListEmbed' 16import {Embed as StarterPackEmbed} from '#/components/StarterPack/StarterPackCard' 17import {Text} from '#/components/Typography' 18 19export const ExternalEmbedGif = ({ 20 onRemove, 21 gif, 22}: { 23 onRemove: () => void 24 gif: Gif 25}) => { 26 const t = useTheme() 27 const {data, error} = useResolveGifQuery(gif) 28 const linkInfo = React.useMemo( 29 () => 30 data && { 31 title: data.title ?? data.uri, 32 uri: data.uri, 33 description: data.description ?? '', 34 thumb: data.thumb?.source.path, 35 }, 36 [data], 37 ) 38 39 const loadingStyle: ViewStyle = { 40 aspectRatio: gif.media_formats.gif.dims[0] / gif.media_formats.gif.dims[1], 41 width: '100%', 42 } 43 44 return ( 45 <View style={[a.overflow_hidden, t.atoms.border_contrast_medium]}> 46 {linkInfo ? ( 47 <View style={{pointerEvents: 'auto'}}> 48 <ExternalEmbed link={linkInfo} hideAlt /> 49 </View> 50 ) : error ? ( 51 <Container style={[a.align_start, a.p_md, a.gap_xs]}> 52 <Text numberOfLines={1} style={t.atoms.text_contrast_high}> 53 {gif.url} 54 </Text> 55 <Text numberOfLines={2} style={[{color: t.palette.negative_400}]}> 56 {cleanError(error)} 57 </Text> 58 </Container> 59 ) : ( 60 <Container style={loadingStyle}> 61 <Loader size="xl" /> 62 </Container> 63 )} 64 <ExternalEmbedRemoveBtn onRemove={onRemove} /> 65 </View> 66 ) 67} 68 69export const ExternalEmbedLink = ({ 70 uri, 71 hasQuote, 72 onRemove, 73}: { 74 uri: string 75 hasQuote: boolean 76 onRemove: () => void 77}) => { 78 const t = useTheme() 79 const {data, error} = useResolveLinkQuery(uri) 80 const linkComponent = React.useMemo(() => { 81 if (data) { 82 if (data.type === 'external') { 83 return ( 84 <ExternalEmbed 85 link={{ 86 title: data.title || uri, 87 uri, 88 description: data.description, 89 thumb: data.thumb?.source.path, 90 }} 91 hideAlt 92 /> 93 ) 94 } else if (data.kind === 'feed') { 95 return ( 96 <ModeratedFeedEmbed 97 embed={{ 98 type: 'feed', 99 view: { 100 $type: 'app.bsky.feed.defs#generatorView', 101 ...data.view, 102 }, 103 }} 104 /> 105 ) 106 } else if (data.kind === 'list') { 107 return ( 108 <ModeratedListEmbed 109 embed={{ 110 type: 'list', 111 view: { 112 $type: 'app.bsky.graph.defs#listView', 113 ...data.view, 114 }, 115 }} 116 /> 117 ) 118 } else if (data.kind === 'starter-pack') { 119 return <StarterPackEmbed starterPack={data.view} /> 120 } 121 } 122 }, [data, uri]) 123 124 if (data?.type === 'record' && hasQuote) { 125 // This is not currently supported by the data model so don't preview it. 126 return null 127 } 128 129 return ( 130 <View style={[a.mb_xl, a.overflow_hidden, t.atoms.border_contrast_medium]}> 131 {linkComponent ? ( 132 <View style={{pointerEvents: 'none'}}>{linkComponent}</View> 133 ) : error ? ( 134 <Container style={[a.align_start, a.p_md, a.gap_xs]}> 135 <Text numberOfLines={1} style={t.atoms.text_contrast_high}> 136 {uri} 137 </Text> 138 <Text numberOfLines={2} style={[{color: t.palette.negative_400}]}> 139 {cleanError(error)} 140 </Text> 141 </Container> 142 ) : ( 143 <Container> 144 <Loader size="xl" /> 145 </Container> 146 )} 147 <ExternalEmbedRemoveBtn onRemove={onRemove} /> 148 </View> 149 ) 150} 151 152function Container({ 153 style, 154 children, 155}: { 156 style?: StyleProp<ViewStyle> 157 children: React.ReactNode 158}) { 159 const t = useTheme() 160 return ( 161 <View 162 style={[ 163 a.rounded_sm, 164 a.border, 165 a.align_center, 166 a.justify_center, 167 a.py_5xl, 168 t.atoms.bg_contrast_25, 169 t.atoms.border_contrast_medium, 170 style, 171 ]}> 172 {children} 173 </View> 174 ) 175}