// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {useCallback, useEffect, useState} from 'react'; import {ActivityIndicator, type StyleProp, Text, View, type ViewStyle} from 'react-native'; import FastImage from 'react-native-fast-image'; import CompassIcon from '@components/compass_icon'; import fetchOpenGraph, {type OpenGraph} from '@share/open_graph'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import {typography} from '@utils/typography'; type Props = { url?: string; theme: Theme; } type OpenGraphImageProps = Props & { style: StyleProp; }; const getStyles = makeStyleSheetFromTheme((theme: Theme) => ({ container: { borderColor: changeOpacity(theme.centerChannelColor, 0.16), borderWidth: 1, borderRadius: 4, flexDirection: 'row', maxHeight: 96, height: 96, marginHorizontal: 20, padding: 12, }, flex: {flex: 1}, image: { alignItems: 'center', borderColor: changeOpacity(theme.centerChannelColor, 0.16), borderRadius: 4, borderWidth: 1, height: 72, justifyContent: 'center', marginLeft: 10, width: 72, }, link: { color: changeOpacity(theme.centerChannelColor, 0.64), marginTop: 4, ...typography('Body', 75, 'Regular'), }, title: { color: theme.linkColor, ...typography('Body', 200, 'SemiBold'), }, })); const OpenGraphImage = ({style, theme, url}: OpenGraphImageProps) => { const [loading, setLoading] = useState(false); const [error, setError] = useState(false); const onLoad = useCallback(() => { setLoading(false); }, []); const onError = useCallback(() => { setError(true); setLoading(false); }, []); return ( {error && !loading && } {loading && } {!error && } ); }; const LinkPreview = ({theme, url}: Props) => { const styles = getStyles(theme); const [data, setData] = useState(); useEffect(() => { if (url) { fetchOpenGraph(url).then(setData); } }, [url]); if (!data || data.error) { return null; } return ( {url} {data!.link} {Boolean(data.imageURL) && } ); }; export default LinkPreview;