mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {useCallback} from 'react'
2import {StyleProp, View, ViewStyle} from 'react-native'
3import {Image} from 'expo-image'
4import {AppBskyEmbedExternal} from '@atproto/api'
5import {msg} from '@lingui/macro'
6import {useLingui} from '@lingui/react'
7
8import {usePalette} from 'lib/hooks/usePalette'
9import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
10import {shareUrl} from 'lib/sharing'
11import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player'
12import {
13 getStarterPackOgCard,
14 parseStarterPackUri,
15} from 'lib/strings/starter-pack'
16import {toNiceDomain} from 'lib/strings/url-helpers'
17import {isNative} from 'platform/detection'
18import {useExternalEmbedsPrefs} from 'state/preferences'
19import {Link} from 'view/com/util/Link'
20import {ExternalGifEmbed} from 'view/com/util/post-embeds/ExternalGifEmbed'
21import {ExternalPlayer} from 'view/com/util/post-embeds/ExternalPlayerEmbed'
22import {GifEmbed} from 'view/com/util/post-embeds/GifEmbed'
23import {atoms as a, useTheme} from '#/alf'
24import {MediaInsetBorder} from '#/components/MediaInsetBorder'
25import {Text} from '../text/Text'
26
27export const ExternalLinkEmbed = ({
28 link,
29 onOpen,
30 style,
31 hideAlt,
32}: {
33 link: AppBskyEmbedExternal.ViewExternal
34 onOpen?: () => void
35 style?: StyleProp<ViewStyle>
36 hideAlt?: boolean
37}) => {
38 const {_} = useLingui()
39 const pal = usePalette('default')
40 const t = useTheme()
41 const {isMobile} = useWebMediaQueries()
42 const externalEmbedPrefs = useExternalEmbedsPrefs()
43
44 const starterPackParsed = parseStarterPackUri(link.uri)
45 const imageUri = starterPackParsed
46 ? getStarterPackOgCard(starterPackParsed.name, starterPackParsed.rkey)
47 : link.thumb
48
49 const embedPlayerParams = React.useMemo(() => {
50 const params = parseEmbedPlayerFromUrl(link.uri)
51
52 if (params && externalEmbedPrefs?.[params.source] !== 'hide') {
53 return params
54 }
55 }, [link.uri, externalEmbedPrefs])
56
57 if (embedPlayerParams?.source === 'tenor') {
58 return <GifEmbed params={embedPlayerParams} link={link} hideAlt={hideAlt} />
59 }
60
61 return (
62 <View style={[a.flex_col, a.w_full]}>
63 <LinkWrapper link={link} onOpen={onOpen} style={style}>
64 {imageUri && !embedPlayerParams ? (
65 <View>
66 <Image
67 style={{
68 aspectRatio: 1.91,
69 borderTopRightRadius: 8,
70 borderTopLeftRadius: 8,
71 }}
72 source={{uri: imageUri}}
73 accessibilityIgnoresInvertColors
74 accessibilityLabel={starterPackParsed ? link.title : undefined}
75 accessibilityHint={
76 starterPackParsed ? _(msg`Navigate to starter pack`) : undefined
77 }
78 />
79 <MediaInsetBorder
80 opaque
81 style={[
82 {
83 borderBottomLeftRadius: 0,
84 borderBottomRightRadius: 0,
85 },
86 ]}
87 />
88 </View>
89 ) : undefined}
90 {embedPlayerParams?.isGif ? (
91 <ExternalGifEmbed link={link} params={embedPlayerParams} />
92 ) : embedPlayerParams ? (
93 <ExternalPlayer link={link} params={embedPlayerParams} />
94 ) : undefined}
95 <View
96 style={[
97 a.border_b,
98 a.border_l,
99 a.border_r,
100 a.flex_1,
101 a.py_sm,
102 t.atoms.border_contrast_low,
103 {
104 borderBottomRightRadius: 8,
105 borderBottomLeftRadius: 8,
106 paddingHorizontal: isMobile ? 10 : 14,
107 },
108 !imageUri && !embedPlayerParams && [a.border, a.rounded_sm],
109 ]}>
110 <Text
111 type="sm"
112 numberOfLines={1}
113 style={[pal.textLight, {marginVertical: 2}]}>
114 {toNiceDomain(link.uri)}
115 </Text>
116
117 {!embedPlayerParams?.isGif && !embedPlayerParams?.dimensions && (
118 <Text type="lg-bold" numberOfLines={3} style={[pal.text]}>
119 {link.title || link.uri}
120 </Text>
121 )}
122 {link.description ? (
123 <Text
124 type="md"
125 numberOfLines={link.thumb ? 2 : 4}
126 style={[pal.text, a.mt_xs]}>
127 {link.description}
128 </Text>
129 ) : undefined}
130 </View>
131 </LinkWrapper>
132 </View>
133 )
134}
135
136function LinkWrapper({
137 link,
138 onOpen,
139 style,
140 children,
141}: {
142 link: AppBskyEmbedExternal.ViewExternal
143 onOpen?: () => void
144 style?: StyleProp<ViewStyle>
145 children: React.ReactNode
146}) {
147 const onShareExternal = useCallback(() => {
148 if (link.uri && isNative) {
149 shareUrl(link.uri)
150 }
151 }, [link.uri])
152
153 return (
154 <Link
155 asAnchor
156 anchorNoUnderline
157 href={link.uri}
158 style={[a.flex_1, a.rounded_sm, style]}
159 onBeforePress={onOpen}
160 onLongPress={onShareExternal}>
161 {children}
162 </Link>
163 )
164}