From 9e1b37be11502389057e1b429243acdeba3d9de4 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 16 Feb 2018 16:34:25 -0200 Subject: [PATCH] [NEW] lastmessage (#236) * attempt to add last message * Custom emoji * status --- __tests__/RoomItem.js | 2 +- __tests__/__snapshots__/RoomItem.js.snap | 695 +++++--- .../__snapshots__/Storyshots.test.js.snap | 1502 +++++++++++------ android/app/src/main/assets/fonts/Feather.ttf | Bin 0 -> 55288 bytes .../com/rocketchatrn/CustomTabsAndroid.java | 2 +- .../com/rocketchatrn/CustomTabsHelper.java | 2 +- .../com/rocketchatrn/MainApplication.java | 3 +- .../rocketchatrn/RocketChatNativePackage.java | 2 +- app/containers/Avatar.js | 6 +- app/containers/MessageActions.js | 7 +- app/containers/message/Markdown.js | 23 +- app/containers/status.js | 39 + app/lib/realm.js | 8 +- app/lib/rocketchat.js | 12 +- app/presentation/RoomItem.js | 209 ++- app/views/RoomView/index.js | 16 +- app/views/RoomsListView/index.js | 23 +- package-lock.json | 2 +- 18 files changed, 1765 insertions(+), 788 deletions(-) create mode 100755 android/app/src/main/assets/fonts/Feather.ttf create mode 100644 app/containers/status.js diff --git a/__tests__/RoomItem.js b/__tests__/RoomItem.js index cc4d76d2..253b5d45 100644 --- a/__tests__/RoomItem.js +++ b/__tests__/RoomItem.js @@ -3,7 +3,7 @@ import { Provider } from 'react-redux'; import { createStore, combineReducers } from 'redux'; -const reducers = combineReducers({settings:() => ({})}); +const reducers = combineReducers({login:() => ({user: {}}), settings:() => ({})}); const store = createStore(reducers); import React from 'react'; diff --git a/__tests__/__snapshots__/RoomItem.js.snap b/__tests__/__snapshots__/RoomItem.js.snap index 23643947..4bb3753e 100644 --- a/__tests__/__snapshots__/RoomItem.js.snap +++ b/__tests__/__snapshots__/RoomItem.js.snap @@ -34,9 +34,11 @@ exports[`render channel 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -48,13 +50,12 @@ exports[`render channel 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#00BCD4", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -75,7 +76,7 @@ exports[`render channel 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ], Object { @@ -93,44 +94,70 @@ exports[`render channel 1`] = ` style={ Object { "flex": 1, + "height": "100%", "marginLeft": 16, "marginRight": 4, } } > - - general - - - Nov 10 - + + general + + + Nov 10 + + + @@ -171,9 +198,11 @@ exports[`render no icon 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -185,13 +214,12 @@ exports[`render no icon 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -212,7 +240,7 @@ exports[`render no icon 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ], Object { @@ -230,44 +258,70 @@ exports[`render no icon 1`] = ` style={ Object { "flex": 1, + "height": "100%", "marginLeft": 16, "marginRight": 4, } } > - - name - - - Nov 10 - + + name + + + Nov 10 + + + @@ -308,9 +362,11 @@ exports[`render private group 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -322,13 +378,12 @@ exports[`render private group 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#FF9800", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -349,7 +404,7 @@ exports[`render private group 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ], Object { @@ -367,44 +422,70 @@ exports[`render private group 1`] = ` style={ Object { "flex": 1, + "height": "100%", "marginLeft": 16, "marginRight": 4, } } > - - private-group - - - Nov 10 - + + private-group + + + Nov 10 + + + @@ -446,9 +527,11 @@ exports[`render unread +999 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -460,13 +543,12 @@ exports[`render unread +999 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -482,7 +564,7 @@ exports[`render unread +999 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -490,70 +572,120 @@ exports[`render unread +999 1`] = ` NA + - - name - - - Nov 10 - - - + name + + + Nov 10 + + + - 999+ - + > + + 999+ + + + @@ -593,9 +725,11 @@ exports[`render unread 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -607,13 +741,12 @@ exports[`render unread 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -629,7 +762,7 @@ exports[`render unread 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -637,70 +770,120 @@ exports[`render unread 1`] = ` NA + - - name - - - Nov 10 - - - + name + + + Nov 10 + + + - 1 - + > + + 1 + + + @@ -740,9 +923,11 @@ exports[`renders correctly 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -754,13 +939,12 @@ exports[`renders correctly 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -776,7 +960,7 @@ exports[`renders correctly 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -784,49 +968,96 @@ exports[`renders correctly 1`] = ` NA + - - name - - - Nov 10 - + + name + + + Nov 10 + + + diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap index 7a0a3c1b..185c7371 100644 --- a/__tests__/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/__snapshots__/Storyshots.test.js.snap @@ -9,7 +9,6 @@ exports[`Storyshots Avatar avatar 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", @@ -46,7 +45,6 @@ exports[`Storyshots Avatar avatar 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#9C27B0", @@ -83,7 +81,6 @@ exports[`Storyshots Avatar avatar 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#9C27B0", @@ -120,7 +117,6 @@ exports[`Storyshots Avatar avatar 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#3F51B5", @@ -190,9 +186,11 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -204,13 +202,12 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#8BC34A", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -226,7 +223,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -234,49 +231,96 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` RC + - - rocket.cat - - - Nov 10 - + + rocket.cat + + + Nov 10 + + + @@ -312,9 +356,11 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -326,13 +372,12 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#8BC34A", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -348,7 +393,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -356,51 +401,98 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` RC + - - rocket.cat - - - Nov 10 - + + rocket.cat + + + Nov 10 + + + @@ -436,9 +528,11 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -450,13 +544,12 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#8BC34A", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -472,7 +565,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -480,70 +573,120 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` RC + - - rocket.cat - - - Nov 10 - - - + rocket.cat + + + Nov 10 + + + - 1 - + > + + 1 + + + + - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - Nov 10 - - - + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + - 9 - + > + + 9 + + + + - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - Nov 10 - - - + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + - 99 - + > + + 99 + + + + - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - Nov 10 - - - + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + - 100 - + > + + 100 + + + + - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - Nov 10 - - - + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + - 999+ - + > + + 999+ + + + + - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries - - - Nov 10 - - - + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + + + Nov 10 + + + - @ 999+ - + > + + @ 999+ + + + + - - W - - - Nov 10 - + + W + + + Nov 10 + + + @@ -1412,9 +1858,11 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -1426,13 +1874,12 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": "#9C27B0", "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -1448,7 +1895,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -1456,49 +1903,96 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` WW + - - WW - - - Nov 10 - + + WW + + + Nov 10 + + + @@ -1534,9 +2028,11 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Array [ Object { "alignItems": "center", + "borderBottomColor": "#ddd", + "borderBottomWidth": 0.5, "flexDirection": "row", "paddingHorizontal": 16, - "paddingVertical": 10, + "paddingVertical": 12, }, undefined, ] @@ -1548,13 +2044,12 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` Object { "alignItems": "center", "justifyContent": "center", - "overflow": "hidden", }, Object { "backgroundColor": undefined, "borderRadius": 4, - "height": 40, - "width": 40, + "height": 46, + "width": 46, }, undefined, ] @@ -1570,7 +2065,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` "color": "#ffffff", }, Object { - "fontSize": 20, + "fontSize": 23, }, ] } @@ -1578,49 +2073,96 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = ` + - - - - - Nov 10 - + + + + + Nov 10 + + + 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 0000000000000000000000000000000000000000..244854c5492eecee3ff136fbe461a517079dcdde GIT binary patch literal 55288 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java b/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java index 605a058e..e0a9db1f 100644 --- a/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java +++ b/android/app/src/main/java/com/rocketchatrn/CustomTabsAndroid.java @@ -1,4 +1,4 @@ -package com.rocketchatrn; +package chat.rocket.reactnative; import android.content.Intent; import android.content.pm.ResolveInfo; diff --git a/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java b/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java index 99934ec3..b7f3eb72 100644 --- a/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java +++ b/android/app/src/main/java/com/rocketchatrn/CustomTabsHelper.java @@ -1,4 +1,4 @@ -package com.rocketchatrn; +package chat.rocket.reactnative; import android.content.Context; import android.content.Intent; diff --git a/android/app/src/main/java/com/rocketchatrn/MainApplication.java b/android/app/src/main/java/com/rocketchatrn/MainApplication.java index beb8cc02..986de10f 100644 --- a/android/app/src/main/java/com/rocketchatrn/MainApplication.java +++ b/android/app/src/main/java/com/rocketchatrn/MainApplication.java @@ -44,7 +44,8 @@ public class MainApplication extends Application implements ReactApplication { new ReactVideoPackage(), new SplashScreenReactPackage(), new RCTToastPackage(), - new KeyboardInputPackage(MainApplication.this) + new KeyboardInputPackage(MainApplication.this), + new RocketChatNativePackage() ); } }; diff --git a/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java b/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java index bbc20f72..16cef019 100644 --- a/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java +++ b/android/app/src/main/java/com/rocketchatrn/RocketChatNativePackage.java @@ -1,4 +1,4 @@ -package com.rocketchatrn; +package chat.rocket.reactnative; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; 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/MessageActions.js b/app/containers/MessageActions.js index e362c69d..6a2de4b4 100644 --- a/app/containers/MessageActions.js +++ b/app/containers/MessageActions.js @@ -18,6 +18,7 @@ import { } from '../actions/messages'; import { showToast } from '../utils/info'; +const returnAnArray = obj => obj || []; @connect( state => ({ showActions: state.messages.showActions, @@ -171,11 +172,11 @@ export default class MessageActions extends React.Component { } setPermissions(permissions) { - this.hasEditPermission = permissions['edit-message'] + this.hasEditPermission = returnAnArray(permissions['edit-message']) .some(item => this.mergedRoles.indexOf(item) !== -1); - this.hasDeletePermission = permissions['delete-message'] + this.hasDeletePermission = returnAnArray(permissions['delete-message']) .some(item => this.mergedRoles.indexOf(item) !== -1); - this.hasForceDeletePermission = permissions['force-delete-message'] + this.hasForceDeletePermission = returnAnArray(permissions['force-delete-message']) .some(item => this.mergedRoles.indexOf(item) !== -1); } diff --git a/app/containers/message/Markdown.js b/app/containers/message/Markdown.js index 805c915f..1b50f901 100644 --- a/app/containers/message/Markdown.js +++ b/app/containers/message/Markdown.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Text, StyleSheet } from 'react-native'; +import { Text, StyleSheet, ViewPropTypes } from 'react-native'; import PropTypes from 'prop-types'; import EasyMarkdown from 'react-native-easy-markdown'; // eslint-disable-line import SimpleMarkdown from 'simple-markdown'; @@ -17,13 +17,15 @@ const BlockCode = ({ node, state }) => ( ); const mentionStyle = { color: '#13679a' }; -const Markdown = ({ msg, customEmojis }) => { +const Markdown = ({ + msg, customEmojis, style, markdownStyle, customRules, renderInline +}) => { if (!msg) { return null; } msg = emojify(msg, { output: 'unicode' }); - const rules = { + const defaultRules = { username: { order: -1, match: SimpleMarkdown.inlineRegex(/^@[0-9a-zA-Z-_.]+/), @@ -121,11 +123,13 @@ const Markdown = ({ msg, customEmojis }) => { }; const codeStyle = StyleSheet.flatten(styles.codeStyle); + style = StyleSheet.flatten(style); return ( {msg} ); @@ -133,7 +137,12 @@ const Markdown = ({ msg, customEmojis }) => { Markdown.propTypes = { msg: PropTypes.string.isRequired, - customEmojis: PropTypes.object + customEmojis: PropTypes.object, + // eslint-disable-next-line react/no-typos + style: ViewPropTypes.style, + markdownStyle: PropTypes.object, + customRules: PropTypes.object, + renderInline: PropTypes.bool }; BlockCode.propTypes = { diff --git a/app/containers/status.js b/app/containers/status.js new file mode 100644 index 00000000..55a78fcc --- /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 && this.props.activeUsers[userId]) || 'offline'; + } + + render() { + return (); + } +} diff --git a/app/lib/realm.js b/app/lib/realm.js index 14766045..bca5a7a1 100644 --- a/app/lib/realm.js +++ b/app/lib/realm.js @@ -49,6 +49,7 @@ const roomsSchema = { properties: { _id: 'string', t: 'string', + lastMessage: 'messages', _updatedAt: { type: 'date', optional: true } } }; @@ -80,7 +81,8 @@ const subscriptionSchema = { // userMentions: 0, // groupMentions: 0, roomUpdatedAt: { type: 'date', optional: true }, - ro: { type: 'bool', optional: true } + ro: { type: 'bool', optional: true }, + lastMessage: { type: 'messages', optional: true } } }; @@ -134,7 +136,7 @@ const attachment = { const url = { name: 'url', properties: { - _id: 'int', + // _id: { type: 'int', optional: true }, url: { type: 'string', optional: true }, title: { type: 'string', optional: true }, description: { type: 'string', optional: true }, @@ -183,7 +185,7 @@ const messagesSchema = { groupable: { type: 'bool', optional: true }, avatar: { type: 'string', optional: true }, attachments: { type: 'list', objectType: 'attachment' }, - urls: { type: 'list', objectType: 'url' }, + urls: { type: 'list', objectType: 'url', default: [] }, _updatedAt: { type: 'date', optional: true }, status: { type: 'int', optional: true }, pinned: { type: 'bool', optional: true }, diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index f56eb1c9..292476bb 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -128,11 +128,12 @@ const RocketChat = { const sub = database.objects('subscriptions').filtered('rid == $0', data._id)[0]; database.write(() => { sub.roomUpdatedAt = data._updatedAt; + sub.lastMessage = data.lastMessage; sub.ro = data.ro; }); } }); - }); + }).catch(console.log); }, me({ server, token, userId }) { @@ -428,6 +429,7 @@ const RocketChat = { const room = rooms.find(({ _id }) => _id === subscription.rid); if (room) { subscription.roomUpdatedAt = room._updatedAt; + subscription.lastMessage = room.lastMessage; subscription.ro = room.ro; } if (subscription.roles) { @@ -435,10 +437,14 @@ const RocketChat = { } return subscription; }); + + 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)); }); + + this.ddp.subscribe('stream-notify-user', `${ login.user.id }/subscriptions-changed`, false); this.ddp.subscribe('stream-notify-user', `${ login.user.id }/rooms-changed`, false); return data; diff --git a/app/presentation/RoomItem.js b/app/presentation/RoomItem.js index d198f91f..946796b7 100644 --- a/app/presentation/RoomItem.js +++ b/app/presentation/RoomItem.js @@ -2,36 +2,60 @@ import React from 'react'; import moment from 'moment'; import PropTypes from 'prop-types'; import { View, Text, StyleSheet } from 'react-native'; + +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'; const styles = StyleSheet.create({ container: { flexDirection: 'row', paddingHorizontal: 16, - paddingVertical: 10, - alignItems: 'center' + paddingVertical: 12, + alignItems: 'center', + borderBottomWidth: 0.5, + borderBottomColor: '#ddd' }, number: { - minWidth: 20, - borderRadius: 3, + minWidth: 25, + borderRadius: 4, backgroundColor: '#1d74f5', color: '#fff', - textAlign: 'center', overflow: 'hidden', fontSize: 14, + paddingVertical: 4, paddingHorizontal: 5, - paddingVertical: 2 + + textAlign: 'center', + alignItems: 'center', + justifyContent: 'center' }, roomNameView: { flex: 1, + height: '100%', marginLeft: 16, marginRight: 4 }, roomName: { flex: 1, - fontSize: 16, - color: '#444' + fontSize: 18, + color: '#444', + + marginRight: 8 + }, + lastMessage: { + flex: 1, + flexShrink: 1, + marginRight: 8, + maxHeight: 20, + overflow: 'hidden', + flexDirection: 'row', + alignItems: 'flex-start', + justifyContent: 'flex-start' }, alert: { fontWeight: 'bold' @@ -39,30 +63,144 @@ const styles = StyleSheet.create({ favorite: { // backgroundColor: '#eee' }, - update: { + row: { + width: '100%', flex: 1, + flexDirection: 'row', + alignItems: 'flex-end', + justifyContent: 'flex-end' + }, + firstRow: { + width: '100%', + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center' + }, + update: { fontSize: 10, - // height: 10, - color: '#888' + 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' } }; +const parseInline = (parse, content, state) => { + const isCurrentlyInline = state.inline || false; + state.inline = true; + const result = parse(content, state); + state.inline = isCurrentlyInline; + return result; +}; +const parseCaptureInline = (capture, parse, state) => ({ content: parseInline(parse, capture[1], state) }); +const customRules = { + strong: { + order: -4, + match: SimpleMarkdown.inlineRegex(/^\*\*([\s\S]+?)\*\*(?!\*)/), + parse: parseCaptureInline, + react: (node, output, state) => ({ + type: 'strong', + key: state.key, + props: { + children: output(node.content, state) + } + }) + }, + text: { + order: -3, + match: SimpleMarkdown.inlineRegex(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/), + parse: capture => ({ content: capture[0] }), + react: node => node.content + } +}; + +const renderNumber = (unread, userMentions) => { + if (!unread || unread <= 0) { + return; + } + + if (unread >= 1000) { + unread = '999+'; + } + + if (userMentions > 0) { + unread = `@ ${ unread }`; + } + + return ( + + { unread } + + ); +}; + +@connect(state => ({ + user: state.login && state.login.user, + StoreLastMessage: state.settings.Store_Last_Message, + customEmojis: state.customEmojis +})) export default class RoomItem extends React.PureComponent { static propTypes = { type: PropTypes.string.isRequired, name: PropTypes.string.isRequired, + StoreLastMessage: PropTypes.bool, _updatedAt: PropTypes.instanceOf(Date), + lastMessage: PropTypes.object, favorite: PropTypes.bool, alert: PropTypes.bool, unread: PropTypes.number, userMentions: PropTypes.number, - baseUrl: PropTypes.string, - onPress: PropTypes.func + id: PropTypes.string, + onPress: PropTypes.func, + customEmojis: PropTypes.object, + user: 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, 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, '') }`; + + const maxChars = 35; + + + if (alert) { + return `**${ msg.slice(0, maxChars) }${ msg.replace(/:[a-z0-9]+:/gi, ':::').length > maxChars ? '...' : '' }**`; + } + return `${ msg.slice(0, maxChars) }${ msg.replace(/:[a-z0-9]+:/gi, ':::').length > maxChars ? '...' : '' }`; } formatDate = date => moment(date).calendar(null, { @@ -72,29 +210,9 @@ export default class RoomItem extends React.PureComponent { sameElse: 'MMM D' }) - renderNumber = (unread, userMentions) => { - if (!unread || unread <= 0) { - return; - } - - if (unread >= 1000) { - unread = '999+'; - } - - if (userMentions > 0) { - unread = `@ ${ unread }`; - } - - return ( - - { unread } - - ); - } - render() { const { - favorite, alert, unread, userMentions, name, _updatedAt + favorite, unread, userMentions, name, _updatedAt, customEmojis, alert } = this.props; const date = this.formatDate(_updatedAt); @@ -117,10 +235,23 @@ export default class RoomItem extends React.PureComponent { {this.icon} - { name } - {_updatedAt ? { date } : null} + + { name } + {_updatedAt ? { date } : null} + + + + {renderNumber(unread, userMentions)} + - {this.renderNumber(unread, userMentions)} ); diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 4d32ca07..ee0594d3 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Text, View, Button, LayoutAnimation } from 'react-native'; +import { Text, View, Button } from 'react-native'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import equal from 'deep-equal'; @@ -51,8 +51,8 @@ export default class RoomView extends React.Component { Message_TimeFormat: PropTypes.string, loading: PropTypes.bool, actionMessage: PropTypes.object, - toggleReactionPicker: PropTypes.func.isRequired, - layoutAnimation: PropTypes.instanceOf(Date) + toggleReactionPicker: PropTypes.func.isRequired + // layoutAnimation: PropTypes.instanceOf(Date) }; static navigationOptions = ({ navigation }) => ({ @@ -90,11 +90,11 @@ export default class RoomView extends React.Component { this.rooms.addListener(this.updateRoom); } - componentWillReceiveProps(nextProps) { - if (this.props.layoutAnimation !== nextProps.layoutAnimation) { - LayoutAnimation.spring(); - } - } + // componentWillReceiveProps(nextProps) { + // // if (this.props.layoutAnimation !== nextProps.layoutAnimation) { + // // LayoutAnimation.spring(); + // // } + // } shouldComponentUpdate(nextProps, nextState) { return !(equal(this.props, nextProps) && equal(this.state, nextState)); } diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index f2292672..75b36c6e 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -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,7 +71,9 @@ export default class RoomsListView extends React.Component { this.search(props.searchText); } } - + // componentWillUpdate() { + // LayoutAnimation.easeInEaseOut(); + // } componentWillUnmount() { this.data.removeAllListeners(); } @@ -79,6 +83,12 @@ export default class RoomsListView extends React.Component { this.search(text); } + getLastMessage = (subscription) => { + const [room] = database.objects('rooms').filtered('_id = $0', subscription.rid).slice(); + console.log('ROOM', room); + return room && room.lastMessage; + } + search(text) { const searchText = text.trim(); if (searchText === '') { @@ -197,20 +207,23 @@ export default class RoomsListView extends React.Component { ); - renderItem = item => ( - { + const id = item.rid.replace(this.props.user.id, '').trim(); + return ( this._onPressItem(item)} - /> - ) + />); + } renderList = () => (