Other attachments
This commit is contained in:
parent
562738bec6
commit
ab627b8d54
|
@ -0,0 +1,20 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, StyleSheet } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
quoteSign: {
|
||||||
|
borderWidth: 2,
|
||||||
|
borderRadius: 4,
|
||||||
|
height: '100%',
|
||||||
|
marginRight: 5
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const QuoteMark = ({ color }) => <View style={[styles.quoteSign, { borderColor: color || '#a0a0a0' }]} />;
|
||||||
|
|
||||||
|
QuoteMark.propTypes = {
|
||||||
|
color: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default QuoteMark;
|
|
@ -0,0 +1,107 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, Text, TouchableOpacity, StyleSheet, Linking } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import Markdown from './Markdown';
|
||||||
|
import QuoteMark from './QuoteMark';
|
||||||
|
import Avatar from '../Avatar';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
button: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 2,
|
||||||
|
alignSelf: 'flex-end'
|
||||||
|
},
|
||||||
|
quoteSign: {
|
||||||
|
borderWidth: 2,
|
||||||
|
borderRadius: 4,
|
||||||
|
borderColor: '#a0a0a0',
|
||||||
|
height: '100%',
|
||||||
|
marginRight: 5
|
||||||
|
},
|
||||||
|
attachmentContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'column'
|
||||||
|
},
|
||||||
|
authorContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
margin: 2
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
fontSize: 10,
|
||||||
|
fontWeight: 'normal',
|
||||||
|
color: '#888',
|
||||||
|
marginLeft: 5
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onPress = (attachment) => {
|
||||||
|
const url = attachment.title_link || attachment.author_link;
|
||||||
|
if (!url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Linking.openURL(attachment.title_link || attachment.author_link);
|
||||||
|
};
|
||||||
|
const Reply = ({ attachment, timeFormat }) => {
|
||||||
|
if (!attachment) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderAvatar = () => {
|
||||||
|
if (!attachment.author_icon && !attachment.author_name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Avatar
|
||||||
|
style={styles.avatar}
|
||||||
|
text={attachment.author_name}
|
||||||
|
size={16}
|
||||||
|
avatar={attachment.author_icon}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderAuthor = () => (
|
||||||
|
attachment.author_name ? <Text style={{ fontWeight: 'bold' }}>{attachment.author_name}</Text> : null
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderTime = () => {
|
||||||
|
const time = attachment.ts ? moment(attachment.ts).format(timeFormat) : null;
|
||||||
|
return time ? <Text style={styles.time}>{ time }</Text> : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderText = () => (
|
||||||
|
attachment.text ? <Markdown msg={attachment.text} /> : null
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => onPress(attachment)}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
<QuoteMark color={attachment.color} />
|
||||||
|
<View style={styles.attachmentContainer}>
|
||||||
|
<View style={styles.authorContainer}>
|
||||||
|
<Text>
|
||||||
|
{renderAvatar()} {renderAuthor()} {renderTime()}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{renderText()}
|
||||||
|
{attachment.attachments.map(attach => <Reply attachment={attach} timeFormat={timeFormat} />)}
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Reply.propTypes = {
|
||||||
|
attachment: PropTypes.object.isRequired,
|
||||||
|
timeFormat: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Reply;
|
|
@ -2,10 +2,11 @@ import React from 'react';
|
||||||
import { View, Text, TouchableOpacity, Linking, StyleSheet, Image } from 'react-native';
|
import { View, Text, TouchableOpacity, Linking, StyleSheet, Image } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import QuoteMark from './QuoteMark';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
button: {
|
button: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
height: 80,
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginVertical: 2
|
marginVertical: 2
|
||||||
|
@ -49,7 +50,7 @@ const Url = ({ url }) => {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity onPress={() => onPress(url.url)} style={styles.button}>
|
<TouchableOpacity onPress={() => onPress(url.url)} style={styles.button}>
|
||||||
<View style={styles.quoteSign} />
|
<QuoteMark />
|
||||||
<Image
|
<Image
|
||||||
style={styles.image}
|
style={styles.image}
|
||||||
source={{ uri: encodeURI(url.image) }}
|
source={{ uri: encodeURI(url.image) }}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Audio from './Audio';
|
||||||
import Video from './Video';
|
import Video from './Video';
|
||||||
import Markdown from './Markdown';
|
import Markdown from './Markdown';
|
||||||
import Url from './Url';
|
import Url from './Url';
|
||||||
|
import Reply from './Reply';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
content: {
|
content: {
|
||||||
|
@ -59,6 +60,10 @@ export default class Message extends React.Component {
|
||||||
return this.props.item.t === 'rm';
|
return this.props.item.t === 'rm';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isPinned() {
|
||||||
|
return this.props.item.t === 'message_pinned';
|
||||||
|
}
|
||||||
|
|
||||||
attachments() {
|
attachments() {
|
||||||
if (this.props.item.attachments.length === 0) {
|
if (this.props.item.attachments.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -74,17 +79,16 @@ export default class Message extends React.Component {
|
||||||
return <Video file={file} baseUrl={baseUrl} user={user} />;
|
return <Video file={file} baseUrl={baseUrl} user={user} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Text>Other type</Text>;
|
return <Reply attachment={file} timeFormat={this.props.Message_TimeFormat} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessageContent() {
|
renderMessageContent() {
|
||||||
if (this.isDeleted()) {
|
if (this.isDeleted()) {
|
||||||
return <Text style={styles.textInfo}>Message removed</Text>;
|
return <Text style={styles.textInfo}>Message removed</Text>;
|
||||||
|
} else if (this.isPinned()) {
|
||||||
|
return <Text style={styles.textInfo}>Message pinned</Text>;
|
||||||
}
|
}
|
||||||
|
return <Markdown msg={this.props.item.msg} />;
|
||||||
return (
|
|
||||||
<Markdown msg={this.props.item.msg} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderUrl() {
|
renderUrl() {
|
||||||
|
@ -130,8 +134,8 @@ export default class Message extends React.Component {
|
||||||
Message_TimeFormat={this.props.Message_TimeFormat}
|
Message_TimeFormat={this.props.Message_TimeFormat}
|
||||||
baseUrl={this.props.baseUrl}
|
baseUrl={this.props.baseUrl}
|
||||||
/>
|
/>
|
||||||
{this.attachments()}
|
|
||||||
{this.renderMessageContent()}
|
{this.renderMessageContent()}
|
||||||
|
{this.attachments()}
|
||||||
{this.renderUrl()}
|
{this.renderUrl()}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -111,7 +111,14 @@ const attachment = {
|
||||||
title: { type: 'string', optional: true },
|
title: { type: 'string', optional: true },
|
||||||
title_link: { type: 'string', optional: true },
|
title_link: { type: 'string', optional: true },
|
||||||
title_link_download: { type: 'bool', optional: true },
|
title_link_download: { type: 'bool', optional: true },
|
||||||
type: { type: 'string', optional: true }
|
type: { type: 'string', optional: true },
|
||||||
|
author_icon: { type: 'string', optional: true },
|
||||||
|
author_name: { type: 'string', optional: true },
|
||||||
|
author_link: { type: 'string', optional: true },
|
||||||
|
text: { type: 'string', optional: true },
|
||||||
|
color: { type: 'string', optional: true },
|
||||||
|
ts: { type: 'date', optional: true },
|
||||||
|
attachments: { type: 'list', objectType: 'attachment' }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,8 @@ const RocketChat = {
|
||||||
if (message.urls) {
|
if (message.urls) {
|
||||||
message.urls = RocketChat._parseUrls(message.urls);
|
message.urls = RocketChat._parseUrls(message.urls);
|
||||||
}
|
}
|
||||||
|
// loadHistory returns message.starred as object
|
||||||
|
// stream-room-messages returns message.starred as an array
|
||||||
message.starred = message.starred && (Array.isArray(message.starred) ? message.starred.length > 0 : !!message.starred);
|
message.starred = message.starred && (Array.isArray(message.starred) ? message.starred.length > 0 : !!message.starred);
|
||||||
return message;
|
return message;
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue