// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import { Image, Linking, Text, View } from 'react-native'; import CustomPropTypes from 'app/constants/custom_prop_types'; import Markdown from 'app/components/markdown'; import FormattedText from 'app/components/formatted_text'; import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; export default class SlackAttachment extends PureComponent { static propTypes = { attachment: PropTypes.object.isRequired, baseTextStyle: CustomPropTypes.Style, blockStyles: PropTypes.object, navigator: PropTypes.object.isRequired, textStyles: PropTypes.object, theme: PropTypes.object }; constructor(props) { super(props); this.state = this.getInitState(); } getCollapsedText = () => { let text = this.props.attachment.text || ''; if ((text.match(/\n/g) || []).length >= 5) { text = text.split('\n').splice(0, 5).join('\n'); } else if (text.length > 400) { text = text.substr(0, 400); } return text; }; getInitState = () => { const shouldCollapse = this.shouldCollapse(); const uncollapsedText = this.props.attachment.text; const collapsedText = shouldCollapse ? this.getCollapsedText() : uncollapsedText; return { shouldCollapse, collapsedText, uncollapsedText, text: shouldCollapse ? collapsedText : uncollapsedText, collapsed: shouldCollapse }; }; getFieldsTable = (style) => { const { attachment, baseTextStyle, blockStyles, navigator, textStyles } = this.props; const fields = attachment.fields; if (!fields || !fields.length) { return null; } const fieldTables = []; let fieldInfos = []; let rowPos = 0; let lastWasLong = false; let nrTables = 0; fields.forEach((field, i) => { if (rowPos === 2 || !(field.short === true) || lastWasLong) { fieldTables.push( {fieldInfos} ); fieldInfos = []; rowPos = 0; nrTables += 1; lastWasLong = false; } fieldInfos.push( {field.title} ); rowPos += 1; lastWasLong = !(field.short === true); }); if (fieldInfos.length > 0) { // Flush last fields fieldTables.push( {fieldInfos} ); } return ( {fieldTables} ); }; openLink = (link) => { if (Linking.canOpenURL(link)) { Linking.openURL(link); } }; shouldCollapse = () => { const text = this.props.attachment.text || ''; return (text.match(/\n/g) || []).length >= 5 || text.length > 400; }; toggleCollapseState = () => { const state = this.state; const text = state.collapsed ? state.uncollapsedText : state.collapsedText; const collapsed = !state.collapsed; this.setState({collapsed, text}); }; render() { const { attachment, baseTextStyle, blockStyles, textStyles, navigator, theme } = this.props; const style = getStyleSheet(theme); let preText; if (attachment.pretext) { preText = ( ); } let borderStyle; if (attachment.color && attachment.color[0] === '#') { borderStyle = {borderLeftColor: attachment.color}; } const author = []; if (attachment.author_name || attachment.author_icon) { if (attachment.author_icon) { author.push( ); } if (attachment.author_name) { let link; let linkStyle; if (attachment.author_link) { link = () => this.openLink(attachment.author_link); linkStyle = style.authorLink; } author.push( {attachment.author_name} ); } } let title; let titleStyle; if (attachment.title) { let titleLink; if (attachment.title_link) { titleStyle = style.titleLink; titleLink = () => this.openLink(attachment.title_link); } title = ( {attachment.title} ); } let thumb; let topStyle; if (attachment.thumb_url) { topStyle = style.topContent; thumb = ( ); } let text; if (attachment.text) { let moreLess; if (this.state.shouldCollapse) { if (this.state.collapsed) { moreLess = ( ); } else { moreLess = ( ); } } text = ( {moreLess} ); } const fields = this.getFieldsTable(style); let image; if (attachment.image_url) { image = ( ); } return ( {preText} {author} {title} {thumb} {text} {fields} {image} ); } } const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { container: { borderColor: changeOpacity(theme.centerChannelColor, 0.15), borderWidth: 1, flex: 1, marginTop: 5, paddingHorizontal: 10, paddingVertical: 7 }, border: { borderLeftColor: changeOpacity(theme.linkColor, 0.6), borderLeftWidth: 3 }, author: { color: changeOpacity(theme.centerChannelColor, 0.5), fontSize: 11 }, authorIcon: { height: 12, marginRight: 3, width: 12 }, authorLink: { color: changeOpacity(theme.linkColor, 0.5) }, title: { color: theme.centerChannelColor, fontWeight: '600', marginVertical: 5 }, titleLink: { color: theme.linkColor }, topContent: { paddingRight: 60 }, thumbContainer: { position: 'absolute', right: 10, top: 10 }, thumb: { height: 45, width: 45 }, moreLess: { color: theme.linkColor, fontSize: 12 }, headingContainer: { flex: 1, flexDirection: 'row', marginBottom: 5, marginTop: 10 }, heading: { color: theme.centerChannelColor, fontWeight: '600' }, bodyContainer: { flex: 1 }, imageContainer: { borderColor: changeOpacity(theme.centerChannelColor, 0.1), borderWidth: 1, borderRadius: 2, marginTop: 5 }, image: { flex: 1, height: 50 } }; });