2020-04-30 20:05:59 +00:00
|
|
|
import React, { useContext } from 'react';
|
2018-09-11 16:32:52 +00:00
|
|
|
import { View, Text, StyleSheet } from 'react-native';
|
2017-12-02 13:19:58 +00:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import moment from 'moment';
|
2021-03-18 13:13:44 +00:00
|
|
|
import { transparentize } from 'color2k';
|
2021-02-26 16:01:45 +00:00
|
|
|
import { dequal } from 'dequal';
|
2017-12-02 13:19:58 +00:00
|
|
|
|
2020-04-30 20:05:59 +00:00
|
|
|
import Touchable from './Touchable';
|
2019-08-27 12:25:38 +00:00
|
|
|
import Markdown from '../markdown';
|
2017-12-28 17:40:10 +00:00
|
|
|
import openLink from '../../utils/openLink';
|
2019-03-29 19:36:07 +00:00
|
|
|
import sharedStyles from '../../views/Styles';
|
2019-12-04 16:39:53 +00:00
|
|
|
import { themes } from '../../constants/colors';
|
2020-04-30 20:05:59 +00:00
|
|
|
import MessageContext from './Context';
|
2017-12-02 13:19:58 +00:00
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
button: {
|
|
|
|
flex: 1,
|
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center',
|
2019-03-29 19:36:07 +00:00
|
|
|
marginTop: 6,
|
2019-11-25 20:01:17 +00:00
|
|
|
alignSelf: 'flex-start',
|
2019-03-29 19:36:07 +00:00
|
|
|
borderWidth: 1,
|
2019-03-01 16:49:11 +00:00
|
|
|
borderRadius: 4
|
2017-12-02 13:19:58 +00:00
|
|
|
},
|
|
|
|
attachmentContainer: {
|
|
|
|
flex: 1,
|
2018-09-11 16:32:52 +00:00
|
|
|
borderRadius: 4,
|
|
|
|
flexDirection: 'column',
|
|
|
|
padding: 15
|
2017-12-02 13:19:58 +00:00
|
|
|
},
|
|
|
|
authorContainer: {
|
2019-02-08 16:34:50 +00:00
|
|
|
flex: 1,
|
2017-12-02 13:19:58 +00:00
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center'
|
|
|
|
},
|
2017-12-04 15:49:15 +00:00
|
|
|
author: {
|
2019-02-08 16:34:50 +00:00
|
|
|
flex: 1,
|
2019-03-01 16:49:11 +00:00
|
|
|
fontSize: 16,
|
2019-03-29 19:36:07 +00:00
|
|
|
...sharedStyles.textMedium
|
2017-12-04 15:49:15 +00:00
|
|
|
},
|
2017-12-02 13:19:58 +00:00
|
|
|
time: {
|
2019-03-01 16:49:11 +00:00
|
|
|
fontSize: 12,
|
2019-03-29 19:36:07 +00:00
|
|
|
marginLeft: 10,
|
|
|
|
...sharedStyles.textRegular,
|
|
|
|
fontWeight: '300'
|
2017-12-02 13:19:58 +00:00
|
|
|
},
|
|
|
|
fieldsContainer: {
|
|
|
|
flex: 1,
|
|
|
|
flexWrap: 'wrap',
|
|
|
|
flexDirection: 'row'
|
|
|
|
},
|
|
|
|
fieldContainer: {
|
|
|
|
flexDirection: 'column',
|
|
|
|
padding: 10
|
|
|
|
},
|
|
|
|
fieldTitle: {
|
2019-03-29 19:36:07 +00:00
|
|
|
fontSize: 14,
|
|
|
|
...sharedStyles.textSemibold
|
|
|
|
},
|
|
|
|
fieldValue: {
|
|
|
|
fontSize: 14,
|
|
|
|
...sharedStyles.textRegular
|
2018-09-11 16:32:52 +00:00
|
|
|
},
|
|
|
|
marginTop: {
|
|
|
|
marginTop: 4
|
2020-11-04 17:25:06 +00:00
|
|
|
},
|
|
|
|
marginBottom: {
|
|
|
|
marginBottom: 4
|
2017-12-02 13:19:58 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-12-04 16:39:53 +00:00
|
|
|
const Title = React.memo(({ attachment, timeFormat, theme }) => {
|
2019-05-20 20:43:50 +00:00
|
|
|
if (!attachment.author_name) {
|
|
|
|
return null;
|
2018-09-19 14:18:32 +00:00
|
|
|
}
|
2019-05-20 20:43:50 +00:00
|
|
|
const time = attachment.ts ? moment(attachment.ts).format(timeFormat) : null;
|
|
|
|
return (
|
|
|
|
<View style={styles.authorContainer}>
|
2019-12-17 14:08:06 +00:00
|
|
|
{attachment.author_name ? <Text style={[styles.author, { color: themes[theme].bodyText }]}>{attachment.author_name}</Text> : null}
|
2019-12-04 16:39:53 +00:00
|
|
|
{time ? <Text style={[styles.time, { color: themes[theme].auxiliaryText }]}>{ time }</Text> : null}
|
2019-05-20 20:43:50 +00:00
|
|
|
</View>
|
|
|
|
);
|
2019-12-04 16:39:53 +00:00
|
|
|
});
|
2017-12-04 15:49:15 +00:00
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
const Description = React.memo(({
|
2020-04-30 20:05:59 +00:00
|
|
|
attachment, getCustomEmoji, theme
|
2018-09-11 16:32:52 +00:00
|
|
|
}) => {
|
2019-05-20 20:43:50 +00:00
|
|
|
const text = attachment.text || attachment.title;
|
|
|
|
if (!text) {
|
2017-12-02 13:19:58 +00:00
|
|
|
return null;
|
|
|
|
}
|
2020-04-30 20:05:59 +00:00
|
|
|
const { baseUrl, user } = useContext(MessageContext);
|
2019-05-20 20:43:50 +00:00
|
|
|
return (
|
|
|
|
<Markdown
|
|
|
|
msg={text}
|
|
|
|
baseUrl={baseUrl}
|
|
|
|
username={user.username}
|
|
|
|
getCustomEmoji={getCustomEmoji}
|
2019-12-04 16:39:53 +00:00
|
|
|
theme={theme}
|
2019-05-20 20:43:50 +00:00
|
|
|
/>
|
2017-12-02 13:19:58 +00:00
|
|
|
);
|
2019-05-20 20:43:50 +00:00
|
|
|
}, (prevProps, nextProps) => {
|
|
|
|
if (prevProps.attachment.text !== nextProps.attachment.text) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (prevProps.attachment.title !== nextProps.attachment.title) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-04 16:39:53 +00:00
|
|
|
if (prevProps.theme !== nextProps.theme) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-05-20 20:43:50 +00:00
|
|
|
return true;
|
|
|
|
});
|
2017-12-02 13:19:58 +00:00
|
|
|
|
2021-03-18 14:44:09 +00:00
|
|
|
const Fields = React.memo(({ attachment, theme, getCustomEmoji }) => {
|
2019-05-20 20:43:50 +00:00
|
|
|
if (!attachment.fields) {
|
|
|
|
return null;
|
|
|
|
}
|
2021-03-18 14:44:09 +00:00
|
|
|
|
|
|
|
const { baseUrl, user } = useContext(MessageContext);
|
2019-05-20 20:43:50 +00:00
|
|
|
return (
|
|
|
|
<View style={styles.fieldsContainer}>
|
|
|
|
{attachment.fields.map(field => (
|
|
|
|
<View key={field.title} style={[styles.fieldContainer, { width: field.short ? '50%' : '100%' }]}>
|
2019-12-17 14:08:06 +00:00
|
|
|
<Text style={[styles.fieldTitle, { color: themes[theme].bodyText }]}>{field.title}</Text>
|
2021-03-18 14:44:09 +00:00
|
|
|
<Markdown
|
|
|
|
msg={field.value}
|
|
|
|
baseUrl={baseUrl}
|
|
|
|
username={user.username}
|
|
|
|
getCustomEmoji={getCustomEmoji}
|
|
|
|
theme={theme}
|
|
|
|
/>
|
2019-05-20 20:43:50 +00:00
|
|
|
</View>
|
|
|
|
))}
|
|
|
|
</View>
|
|
|
|
);
|
2021-02-26 16:01:45 +00:00
|
|
|
}, (prevProps, nextProps) => dequal(prevProps.attachment.fields, nextProps.attachment.fields) && prevProps.theme === nextProps.theme);
|
2017-12-02 13:19:58 +00:00
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
const Reply = React.memo(({
|
2020-06-15 14:00:46 +00:00
|
|
|
attachment, timeFormat, index, getCustomEmoji, theme
|
2019-05-20 20:43:50 +00:00
|
|
|
}) => {
|
|
|
|
if (!attachment) {
|
|
|
|
return null;
|
|
|
|
}
|
2020-04-30 20:05:59 +00:00
|
|
|
const { baseUrl, user } = useContext(MessageContext);
|
2017-12-04 15:49:15 +00:00
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
const onPress = () => {
|
|
|
|
let url = attachment.title_link || attachment.author_link;
|
|
|
|
if (!url) {
|
|
|
|
return;
|
2018-09-19 14:18:32 +00:00
|
|
|
}
|
2019-05-20 20:43:50 +00:00
|
|
|
if (attachment.type === 'file') {
|
2020-05-08 17:07:58 +00:00
|
|
|
if (!url.startsWith('http')) {
|
|
|
|
url = `${ baseUrl }${ url }`;
|
|
|
|
}
|
|
|
|
url = `${ url }?rc_uid=${ user.id }&rc_token=${ user.token }`;
|
2017-12-02 13:19:58 +00:00
|
|
|
}
|
2019-12-04 16:39:53 +00:00
|
|
|
openLink(url, theme);
|
2017-12-02 13:19:58 +00:00
|
|
|
};
|
|
|
|
|
2021-04-01 13:32:03 +00:00
|
|
|
let { borderColor, chatComponentBackground: backgroundColor } = themes[theme];
|
|
|
|
try {
|
|
|
|
if (attachment.color) {
|
|
|
|
backgroundColor = transparentize(attachment.color, 0.80);
|
|
|
|
borderColor = attachment.color;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// fallback to default
|
|
|
|
}
|
|
|
|
|
2017-12-02 13:19:58 +00:00
|
|
|
return (
|
2020-11-04 17:25:06 +00:00
|
|
|
<>
|
|
|
|
<Touchable
|
|
|
|
onPress={onPress}
|
|
|
|
style={[
|
|
|
|
styles.button,
|
|
|
|
index > 0 && styles.marginTop,
|
|
|
|
attachment.description && styles.marginBottom,
|
|
|
|
{
|
2021-04-01 13:32:03 +00:00
|
|
|
backgroundColor, borderColor
|
2020-11-04 17:25:06 +00:00
|
|
|
}
|
|
|
|
]}
|
|
|
|
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
|
|
|
>
|
|
|
|
<View style={styles.attachmentContainer}>
|
|
|
|
<Title
|
|
|
|
attachment={attachment}
|
|
|
|
timeFormat={timeFormat}
|
|
|
|
theme={theme}
|
|
|
|
/>
|
|
|
|
<Description
|
|
|
|
attachment={attachment}
|
|
|
|
getCustomEmoji={getCustomEmoji}
|
|
|
|
theme={theme}
|
|
|
|
/>
|
2021-03-18 14:44:09 +00:00
|
|
|
<Fields
|
|
|
|
attachment={attachment}
|
|
|
|
getCustomEmoji={getCustomEmoji}
|
|
|
|
theme={theme}
|
|
|
|
/>
|
2020-11-04 17:25:06 +00:00
|
|
|
</View>
|
|
|
|
</Touchable>
|
|
|
|
<Markdown
|
|
|
|
msg={attachment.description}
|
|
|
|
baseUrl={baseUrl}
|
|
|
|
username={user.username}
|
|
|
|
getCustomEmoji={getCustomEmoji}
|
|
|
|
theme={theme}
|
|
|
|
/>
|
|
|
|
</>
|
2017-12-02 13:19:58 +00:00
|
|
|
);
|
2021-02-26 16:01:45 +00:00
|
|
|
}, (prevProps, nextProps) => dequal(prevProps.attachment, nextProps.attachment) && prevProps.theme === nextProps.theme);
|
2017-12-02 13:19:58 +00:00
|
|
|
|
|
|
|
Reply.propTypes = {
|
2019-05-20 20:43:50 +00:00
|
|
|
attachment: PropTypes.object,
|
|
|
|
timeFormat: PropTypes.string,
|
|
|
|
index: PropTypes.number,
|
2019-12-04 16:39:53 +00:00
|
|
|
theme: PropTypes.string,
|
2020-06-15 14:00:46 +00:00
|
|
|
getCustomEmoji: PropTypes.func
|
2019-05-20 20:43:50 +00:00
|
|
|
};
|
|
|
|
Reply.displayName = 'MessageReply';
|
|
|
|
|
|
|
|
Title.propTypes = {
|
|
|
|
attachment: PropTypes.object,
|
2019-12-04 16:39:53 +00:00
|
|
|
timeFormat: PropTypes.string,
|
|
|
|
theme: PropTypes.string
|
2019-05-20 20:43:50 +00:00
|
|
|
};
|
|
|
|
Title.displayName = 'MessageReplyTitle';
|
|
|
|
|
|
|
|
Description.propTypes = {
|
|
|
|
attachment: PropTypes.object,
|
2019-12-04 16:39:53 +00:00
|
|
|
getCustomEmoji: PropTypes.func,
|
|
|
|
theme: PropTypes.string
|
2019-05-20 20:43:50 +00:00
|
|
|
};
|
|
|
|
Description.displayName = 'MessageReplyDescription';
|
|
|
|
|
|
|
|
Fields.propTypes = {
|
2019-12-04 16:39:53 +00:00
|
|
|
attachment: PropTypes.object,
|
2021-03-18 14:44:09 +00:00
|
|
|
theme: PropTypes.string,
|
|
|
|
getCustomEmoji: PropTypes.func
|
2017-12-02 13:19:58 +00:00
|
|
|
};
|
2019-05-20 20:43:50 +00:00
|
|
|
Fields.displayName = 'MessageReplyFields';
|
2017-12-02 13:19:58 +00:00
|
|
|
|
2020-06-15 14:00:46 +00:00
|
|
|
export default Reply;
|