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