status on lastmessage

This commit is contained in:
Guilherme Gazzo 2018-02-16 13:55:50 -02:00
parent a286572861
commit 93644ecb02
No known key found for this signature in database
GPG Key ID: 1F85C9AD922D0829
7 changed files with 112 additions and 32 deletions

Binary file not shown.

View File

@ -8,7 +8,7 @@ import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
iconContainer: { iconContainer: {
overflow: 'hidden', // overflow: 'hidden',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center'
}, },
@ -31,7 +31,8 @@ export default class Avatar extends React.PureComponent {
avatar: PropTypes.string, avatar: PropTypes.string,
size: PropTypes.number, size: PropTypes.number,
borderRadius: PropTypes.number, borderRadius: PropTypes.number,
type: PropTypes.string type: PropTypes.string,
children: PropTypes.object
}; };
render() { render() {
const { const {
@ -68,6 +69,7 @@ export default class Avatar extends React.PureComponent {
<View style={[styles.iconContainer, iconContainerStyle, style]}> <View style={[styles.iconContainer, iconContainerStyle, style]}>
<Text style={[styles.avatarInitials, avatarInitialsStyle]} allowFontScaling={false}>{initials}</Text> <Text style={[styles.avatarInitials, avatarInitialsStyle]} allowFontScaling={false}>{initials}</Text>
{image} {image}
{this.props.children}
</View>); </View>);
} }

View File

@ -138,6 +138,7 @@ const Markdown = ({
Markdown.propTypes = { Markdown.propTypes = {
msg: PropTypes.string.isRequired, msg: PropTypes.string.isRequired,
customEmojis: PropTypes.object, customEmojis: PropTypes.object,
// eslint-disable-next-line react/no-typos
style: ViewPropTypes.style, style: ViewPropTypes.style,
markdownStyle: PropTypes.object, markdownStyle: PropTypes.object,
customRules: PropTypes.object, customRules: PropTypes.object,

39
app/containers/status.js Normal file
View File

@ -0,0 +1,39 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { StyleSheet, View, ViewPropTypes } from 'react-native';
import { STATUS_COLORS } from '../constants/colors';
const styles = StyleSheet.create({
status: {
borderRadius: 16,
width: 16,
height: 16
}
});
@connect(state => ({
activeUsers: state.activeUsers
}))
export default class Status extends React.Component {
static propTypes = {
style: ViewPropTypes.style,
id: PropTypes.string,
activeUsers: PropTypes.object
};
shouldComponentUpdate(nextProps) {
const userId = this.props.id;
return this.status !== nextProps.activeUsers[userId];
}
get status() {
const userId = this.props.id;
return this.props.activeUsers[userId] || 'offline';
}
render() {
return (<View style={[styles.status, this.props.style, { backgroundColor: STATUS_COLORS[this.status] }]} />);
}
}

View File

@ -438,14 +438,12 @@ const RocketChat = {
return subscription; return subscription;
}); });
try {
database.write(() => { database.write(() => {
data.forEach(subscription => database.create('subscriptions', subscription, true)); data.forEach(subscription => database.create('subscriptions', subscription, true));
// rooms.forEach(room => database.create('rooms', room, true)); // rooms.forEach(room => database.create('rooms', room, true));
}); });
} catch (e) {
alert(JSON.stringify(e));
}
this.ddp.subscribe('stream-notify-user', `${ login.user.id }/subscriptions-changed`, false); this.ddp.subscribe('stream-notify-user', `${ login.user.id }/subscriptions-changed`, false);
this.ddp.subscribe('stream-notify-user', `${ login.user.id }/rooms-changed`, false); this.ddp.subscribe('stream-notify-user', `${ login.user.id }/rooms-changed`, false);

View File

@ -2,11 +2,12 @@ import React from 'react';
import moment from 'moment'; import moment from 'moment';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { View, Text, StyleSheet } from 'react-native'; import { View, Text, StyleSheet } from 'react-native';
import { emojify } from 'react-emojione';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SimpleMarkdown from 'simple-markdown'; import SimpleMarkdown from 'simple-markdown';
import Avatar from '../containers/Avatar'; import Avatar from '../containers/Avatar';
import Status from '../containers/status';
import Touch from '../utils/touch/index'; //eslint-disable-line import Touch from '../utils/touch/index'; //eslint-disable-line
import Markdown from '../containers/message/Markdown'; import Markdown from '../containers/message/Markdown';
@ -15,7 +16,7 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
paddingHorizontal: 16, paddingHorizontal: 16,
paddingVertical: 12, paddingVertical: 12,
alignItems: 'flex-start', alignItems: 'center',
borderBottomWidth: 0.5, borderBottomWidth: 0.5,
borderBottomColor: '#ddd' borderBottomColor: '#ddd'
}, },
@ -43,13 +44,18 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
fontSize: 18, fontSize: 18,
color: '#444', color: '#444',
fontWeight: 'bold',
marginRight: 8 marginRight: 8
}, },
lastMessage: { lastMessage: {
flex: 1, flex: 1,
flexShrink: 1, flexShrink: 1,
marginRight: 8 marginRight: 8,
maxHeight: 20,
overflow: 'hidden',
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'flex-start'
}, },
alert: { alert: {
fontWeight: 'bold' fontWeight: 'bold'
@ -58,6 +64,13 @@ const styles = StyleSheet.create({
// backgroundColor: '#eee' // backgroundColor: '#eee'
}, },
row: { row: {
width: '100%',
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'flex-end'
},
firstRow: {
width: '100%', width: '100%',
flex: 1, flex: 1,
flexDirection: 'row', flexDirection: 'row',
@ -69,6 +82,13 @@ const styles = StyleSheet.create({
color: '#888', color: '#888',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center' justifyContent: 'center'
},
status: {
position: 'absolute',
bottom: -3,
right: -3,
borderWidth: 3,
borderColor: '#fff'
} }
}); });
const markdownStyle = { block: { marginBottom: 0, flexWrap: 'wrap', flexDirection: 'row' } }; const markdownStyle = { block: { marginBottom: 0, flexWrap: 'wrap', flexDirection: 'row' } };
@ -123,6 +143,7 @@ const renderNumber = (unread, userMentions) => {
}; };
@connect(state => ({ @connect(state => ({
user: state.login.user,
StoreLastMessage: state.settings.Store_Last_Message, StoreLastMessage: state.settings.Store_Last_Message,
customEmojis: state.customEmojis customEmojis: state.customEmojis
})) }))
@ -137,28 +158,43 @@ export default class RoomItem extends React.PureComponent {
alert: PropTypes.bool, alert: PropTypes.bool,
unread: PropTypes.number, unread: PropTypes.number,
userMentions: PropTypes.number, userMentions: PropTypes.number,
baseUrl: PropTypes.string, id: PropTypes.string,
onPress: PropTypes.func, onPress: PropTypes.func,
customEmojis: PropTypes.object customEmojis: PropTypes.object
} }
get icon() { get icon() {
const { type, name, baseUrl } = this.props; const {
return <Avatar text={name} baseUrl={baseUrl} size={56} type={type} />; type, name, id
} = this.props;
return (<Avatar text={name} size={46} type={type}>{type === 'd' ? <Status style={styles.status} id={id} /> : null }</Avatar>);
} }
get lastMessage() { get lastMessage() {
const { const {
lastMessage, alert lastMessage, alert, type
} = this.props; } = this.props;
if (!this.props.StoreLastMessage) { if (!this.props.StoreLastMessage) {
return ''; return '';
} }
if (!lastMessage) {
return 'No Message';
}
let prefix = '';
if (lastMessage.u.username === this.props.user.username) {
prefix = 'You: ';
} else if (type !== 'd') {
prefix = `${ lastMessage.u.username }: `;
}
const msg = `${ prefix }${ lastMessage.msg.replace(/[\n\t\r]/igm, '') }`;
let msg = lastMessage ? `${ lastMessage.u.username }: ${ emojify(lastMessage.msg, { output: 'unicode' }) }` : 'No Message';
if (alert) { if (alert) {
msg = `**${ msg }**`; return `**${ msg.slice(0, 30) }${ msg.replace(/:[a-z0-9]+:/gi, ':::').length > 30 ? '...' : '' }**`;
} }
return msg; return msg;
} }
@ -172,7 +208,7 @@ export default class RoomItem extends React.PureComponent {
render() { render() {
const { const {
favorite, unread, userMentions, name, _updatedAt, customEmojis, baseUrl favorite, unread, userMentions, name, _updatedAt, customEmojis, alert
} = this.props; } = this.props;
const date = this.formatDate(_updatedAt); const date = this.formatDate(_updatedAt);
@ -195,19 +231,19 @@ export default class RoomItem extends React.PureComponent {
<View style={[styles.container, favorite && styles.favorite]}> <View style={[styles.container, favorite && styles.favorite]}>
{this.icon} {this.icon}
<View style={styles.roomNameView}> <View style={styles.roomNameView}>
<View style={styles.row}> <View style={styles.firstRow}>
<Text style={styles.roomName} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text> <Text style={[styles.roomName, alert && styles.alert]} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text>
{_updatedAt ? <Text style={styles.update} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null} {_updatedAt ? <Text style={styles.update} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null}
</View> </View>
<View style={styles.row}> <View style={styles.row}>
<Markdown <Markdown
msg={this.lastMessage} msg={this.lastMessage}
customEmojis={customEmojis} customEmojis={customEmojis}
baseUrl={baseUrl}
style={styles.lastMessage} style={styles.lastMessage}
markdownStyle={markdownStyle} markdownStyle={markdownStyle}
customRules={customRules} customRules={customRules}
renderInline renderInline
numberOfLines={1}
/> />
{renderNumber(unread, userMentions)} {renderNumber(unread, userMentions)}
</View> </View>

View File

@ -3,7 +3,7 @@ import { ListView } from 'realm/react-native';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/Ionicons'; import Icon from 'react-native-vector-icons/Ionicons';
import { Platform, View, TextInput, SafeAreaView, LayoutAnimation } from 'react-native'; import { Platform, View, TextInput, SafeAreaView } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as actions from '../../actions'; import * as actions from '../../actions';
import * as server from '../../actions/connect'; import * as server from '../../actions/connect';
@ -18,6 +18,7 @@ import styles from './styles';
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
@connect(state => ({ @connect(state => ({
user: state.login.user,
server: state.server.server, server: state.server.server,
login: state.login, login: state.login,
Site_Url: state.settings.Site_Url, Site_Url: state.settings.Site_Url,
@ -31,6 +32,7 @@ const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
export default class RoomsListView extends React.Component { export default class RoomsListView extends React.Component {
static propTypes = { static propTypes = {
navigation: PropTypes.object.isRequired, navigation: PropTypes.object.isRequired,
user: PropTypes.object,
Site_Url: PropTypes.string, Site_Url: PropTypes.string,
server: PropTypes.string, server: PropTypes.string,
searchText: PropTypes.string searchText: PropTypes.string
@ -69,9 +71,9 @@ export default class RoomsListView extends React.Component {
this.search(props.searchText); this.search(props.searchText);
} }
} }
componentWillUpdate() { // componentWillUpdate() {
LayoutAnimation.easeInEaseOut(); // LayoutAnimation.easeInEaseOut();
} // }
componentWillUnmount() { componentWillUnmount() {
this.data.removeAllListeners(); this.data.removeAllListeners();
} }
@ -205,8 +207,9 @@ export default class RoomsListView extends React.Component {
</View> </View>
); );
renderItem = item => ( renderItem = (item) => {
<RoomItem const id = item.rid.replace(this.props.user.id, '').trim();
return (<RoomItem
alert={item.alert} alert={item.alert}
unread={item.unread} unread={item.unread}
userMentions={item.userMentions} userMentions={item.userMentions}
@ -215,11 +218,12 @@ export default class RoomsListView extends React.Component {
name={item.name} name={item.name}
_updatedAt={item.roomUpdatedAt} _updatedAt={item.roomUpdatedAt}
key={item._id} key={item._id}
id={id}
type={item.t} type={item.t}
baseUrl={this.props.Site_Url} baseUrl={this.props.Site_Url}
onPress={() => this._onPressItem(item)} onPress={() => this._onPressItem(item)}
/> />);
) }
renderList = () => ( renderList = () => (
<ListView <ListView