diff --git a/android/app/src/main/assets/fonts/Feather.ttf b/android/app/src/main/assets/fonts/Feather.ttf new file mode 100755 index 00000000..244854c5 Binary files /dev/null and b/android/app/src/main/assets/fonts/Feather.ttf differ diff --git a/app/containers/Avatar.js b/app/containers/Avatar.js index f547b778..3ab6c266 100644 --- a/app/containers/Avatar.js +++ b/app/containers/Avatar.js @@ -8,7 +8,7 @@ import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; const styles = StyleSheet.create({ iconContainer: { - overflow: 'hidden', + // overflow: 'hidden', justifyContent: 'center', alignItems: 'center' }, @@ -31,7 +31,8 @@ export default class Avatar extends React.PureComponent { avatar: PropTypes.string, size: PropTypes.number, borderRadius: PropTypes.number, - type: PropTypes.string + type: PropTypes.string, + children: PropTypes.object }; render() { const { @@ -68,6 +69,7 @@ export default class Avatar extends React.PureComponent { {initials} {image} + {this.props.children} ); } diff --git a/app/containers/message/Markdown.js b/app/containers/message/Markdown.js index 3303f29c..1b50f901 100644 --- a/app/containers/message/Markdown.js +++ b/app/containers/message/Markdown.js @@ -138,6 +138,7 @@ const Markdown = ({ Markdown.propTypes = { msg: PropTypes.string.isRequired, customEmojis: PropTypes.object, + // eslint-disable-next-line react/no-typos style: ViewPropTypes.style, markdownStyle: PropTypes.object, customRules: PropTypes.object, diff --git a/app/containers/status.js b/app/containers/status.js new file mode 100644 index 00000000..d1351a27 --- /dev/null +++ b/app/containers/status.js @@ -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 (); + } +} diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index fc0cc31a..292476bb 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -438,14 +438,12 @@ const RocketChat = { return subscription; }); - try { - database.write(() => { - data.forEach(subscription => database.create('subscriptions', subscription, true)); - // rooms.forEach(room => database.create('rooms', room, true)); - }); - } catch (e) { - alert(JSON.stringify(e)); - } + + database.write(() => { + data.forEach(subscription => database.create('subscriptions', subscription, true)); + // rooms.forEach(room => database.create('rooms', room, true)); + }); + this.ddp.subscribe('stream-notify-user', `${ login.user.id }/subscriptions-changed`, false); this.ddp.subscribe('stream-notify-user', `${ login.user.id }/rooms-changed`, false); diff --git a/app/presentation/RoomItem.js b/app/presentation/RoomItem.js index 6a702530..7bd7d08a 100644 --- a/app/presentation/RoomItem.js +++ b/app/presentation/RoomItem.js @@ -2,11 +2,12 @@ import React from 'react'; import moment from 'moment'; import PropTypes from 'prop-types'; import { View, Text, StyleSheet } from 'react-native'; -import { emojify } from 'react-emojione'; + import { connect } from 'react-redux'; import SimpleMarkdown from 'simple-markdown'; import Avatar from '../containers/Avatar'; +import Status from '../containers/status'; import Touch from '../utils/touch/index'; //eslint-disable-line import Markdown from '../containers/message/Markdown'; @@ -15,7 +16,7 @@ const styles = StyleSheet.create({ flexDirection: 'row', paddingHorizontal: 16, paddingVertical: 12, - alignItems: 'flex-start', + alignItems: 'center', borderBottomWidth: 0.5, borderBottomColor: '#ddd' }, @@ -43,13 +44,18 @@ const styles = StyleSheet.create({ flex: 1, fontSize: 18, color: '#444', - fontWeight: 'bold', + marginRight: 8 }, lastMessage: { flex: 1, flexShrink: 1, - marginRight: 8 + marginRight: 8, + maxHeight: 20, + overflow: 'hidden', + flexDirection: 'row', + alignItems: 'flex-start', + justifyContent: 'flex-start' }, alert: { fontWeight: 'bold' @@ -58,6 +64,13 @@ const styles = StyleSheet.create({ // backgroundColor: '#eee' }, row: { + width: '100%', + flex: 1, + flexDirection: 'row', + alignItems: 'flex-end', + justifyContent: 'flex-end' + }, + firstRow: { width: '100%', flex: 1, flexDirection: 'row', @@ -69,6 +82,13 @@ const styles = StyleSheet.create({ color: '#888', alignItems: 'center', justifyContent: 'center' + }, + status: { + position: 'absolute', + bottom: -3, + right: -3, + borderWidth: 3, + borderColor: '#fff' } }); const markdownStyle = { block: { marginBottom: 0, flexWrap: 'wrap', flexDirection: 'row' } }; @@ -123,6 +143,7 @@ const renderNumber = (unread, userMentions) => { }; @connect(state => ({ + user: state.login.user, StoreLastMessage: state.settings.Store_Last_Message, customEmojis: state.customEmojis })) @@ -137,28 +158,43 @@ export default class RoomItem extends React.PureComponent { alert: PropTypes.bool, unread: PropTypes.number, userMentions: PropTypes.number, - baseUrl: PropTypes.string, + id: PropTypes.string, onPress: PropTypes.func, customEmojis: PropTypes.object } get icon() { - const { type, name, baseUrl } = this.props; - return ; + const { + type, name, id + } = this.props; + return ({type === 'd' ? : null }); } get lastMessage() { const { - lastMessage, alert + lastMessage, alert, type } = this.props; if (!this.props.StoreLastMessage) { 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) { - msg = `**${ msg }**`; + return `**${ msg.slice(0, 30) }${ msg.replace(/:[a-z0-9]+:/gi, ':::').length > 30 ? '...' : '' }**`; } return msg; } @@ -172,7 +208,7 @@ export default class RoomItem extends React.PureComponent { render() { const { - favorite, unread, userMentions, name, _updatedAt, customEmojis, baseUrl + favorite, unread, userMentions, name, _updatedAt, customEmojis, alert } = this.props; const date = this.formatDate(_updatedAt); @@ -195,19 +231,19 @@ export default class RoomItem extends React.PureComponent { {this.icon} - - { name } + + { name } {_updatedAt ? { date } : null} {renderNumber(unread, userMentions)} diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index a495be77..75b36c6e 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -3,7 +3,7 @@ import { ListView } from 'realm/react-native'; import React from 'react'; import PropTypes from 'prop-types'; 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 * as actions from '../../actions'; import * as server from '../../actions/connect'; @@ -18,6 +18,7 @@ import styles from './styles'; const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); @connect(state => ({ + user: state.login.user, server: state.server.server, login: state.login, 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 { static propTypes = { navigation: PropTypes.object.isRequired, + user: PropTypes.object, Site_Url: PropTypes.string, server: PropTypes.string, searchText: PropTypes.string @@ -69,9 +71,9 @@ export default class RoomsListView extends React.Component { this.search(props.searchText); } } - componentWillUpdate() { - LayoutAnimation.easeInEaseOut(); - } + // componentWillUpdate() { + // LayoutAnimation.easeInEaseOut(); + // } componentWillUnmount() { this.data.removeAllListeners(); } @@ -205,8 +207,9 @@ export default class RoomsListView extends React.Component { ); - renderItem = item => ( - { + const id = item.rid.replace(this.props.user.id, '').trim(); + return ( this._onPressItem(item)} - /> - ) + />); + } renderList = () => (