[NEW] lastmessage (#236)

* attempt to add last message

* Custom emoji

* status
This commit is contained in:
Guilherme Gazzo 2018-02-16 16:34:25 -02:00 committed by GitHub
parent 9222d4567a
commit 9e1b37be11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1765 additions and 788 deletions

View File

@ -3,7 +3,7 @@ import { Provider } from 'react-redux';
import { createStore, combineReducers } from 'redux'; import { createStore, combineReducers } from 'redux';
const reducers = combineReducers({settings:() => ({})}); const reducers = combineReducers({login:() => ({user: {}}), settings:() => ({})});
const store = createStore(reducers); const store = createStore(reducers);
import React from 'react'; import React from 'react';

View File

@ -34,9 +34,11 @@ exports[`render channel 1`] = `
Array [ Array [
Object { Object {
"alignItems": "center", "alignItems": "center",
"borderBottomColor": "#ddd",
"borderBottomWidth": 0.5,
"flexDirection": "row", "flexDirection": "row",
"paddingHorizontal": 16, "paddingHorizontal": 16,
"paddingVertical": 10, "paddingVertical": 12,
}, },
undefined, undefined,
] ]
@ -48,13 +50,12 @@ exports[`render channel 1`] = `
Object { Object {
"alignItems": "center", "alignItems": "center",
"justifyContent": "center", "justifyContent": "center",
"overflow": "hidden",
}, },
Object { Object {
"backgroundColor": "#00BCD4", "backgroundColor": "#00BCD4",
"borderRadius": 4, "borderRadius": 4,
"height": 40, "height": 46,
"width": 40, "width": 46,
}, },
undefined, undefined,
] ]
@ -75,7 +76,7 @@ exports[`render channel 1`] = `
"color": "#ffffff", "color": "#ffffff",
}, },
Object { Object {
"fontSize": 20, "fontSize": 23,
}, },
], ],
Object { Object {
@ -93,44 +94,70 @@ exports[`render channel 1`] = `
style={ style={
Object { Object {
"flex": 1, "flex": 1,
"height": "100%",
"marginLeft": 16, "marginLeft": 16,
"marginRight": 4, "marginRight": 4,
} }
} }
> >
<Text <View
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 16,
},
undefined,
]
}
>
general
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={ style={
Object { Object {
"color": "#888", "alignItems": "center",
"flex": 1, "flex": 1,
"fontSize": 10, "flexDirection": "row",
"justifyContent": "center",
"width": "100%",
} }
} }
> >
Nov 10 <Text
</Text> accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 18,
"marginRight": 8,
},
undefined,
]
}
>
general
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Object {
"alignItems": "center",
"color": "#888",
"fontSize": 10,
"justifyContent": "center",
}
}
>
Nov 10
</Text>
</View>
<View
style={
Object {
"alignItems": "flex-end",
"flex": 1,
"flexDirection": "row",
"justifyContent": "flex-end",
"width": "100%",
}
}
/>
</View> </View>
</View> </View>
</View> </View>
@ -171,9 +198,11 @@ exports[`render no icon 1`] = `
Array [ Array [
Object { Object {
"alignItems": "center", "alignItems": "center",
"borderBottomColor": "#ddd",
"borderBottomWidth": 0.5,
"flexDirection": "row", "flexDirection": "row",
"paddingHorizontal": 16, "paddingHorizontal": 16,
"paddingVertical": 10, "paddingVertical": 12,
}, },
undefined, undefined,
] ]
@ -185,13 +214,12 @@ exports[`render no icon 1`] = `
Object { Object {
"alignItems": "center", "alignItems": "center",
"justifyContent": "center", "justifyContent": "center",
"overflow": "hidden",
}, },
Object { Object {
"backgroundColor": "#3F51B5", "backgroundColor": "#3F51B5",
"borderRadius": 4, "borderRadius": 4,
"height": 40, "height": 46,
"width": 40, "width": 46,
}, },
undefined, undefined,
] ]
@ -212,7 +240,7 @@ exports[`render no icon 1`] = `
"color": "#ffffff", "color": "#ffffff",
}, },
Object { Object {
"fontSize": 20, "fontSize": 23,
}, },
], ],
Object { Object {
@ -230,44 +258,70 @@ exports[`render no icon 1`] = `
style={ style={
Object { Object {
"flex": 1, "flex": 1,
"height": "100%",
"marginLeft": 16, "marginLeft": 16,
"marginRight": 4, "marginRight": 4,
} }
} }
> >
<Text <View
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 16,
},
undefined,
]
}
>
name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={ style={
Object { Object {
"color": "#888", "alignItems": "center",
"flex": 1, "flex": 1,
"fontSize": 10, "flexDirection": "row",
"justifyContent": "center",
"width": "100%",
} }
} }
> >
Nov 10 <Text
</Text> accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 18,
"marginRight": 8,
},
undefined,
]
}
>
name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Object {
"alignItems": "center",
"color": "#888",
"fontSize": 10,
"justifyContent": "center",
}
}
>
Nov 10
</Text>
</View>
<View
style={
Object {
"alignItems": "flex-end",
"flex": 1,
"flexDirection": "row",
"justifyContent": "flex-end",
"width": "100%",
}
}
/>
</View> </View>
</View> </View>
</View> </View>
@ -308,9 +362,11 @@ exports[`render private group 1`] = `
Array [ Array [
Object { Object {
"alignItems": "center", "alignItems": "center",
"borderBottomColor": "#ddd",
"borderBottomWidth": 0.5,
"flexDirection": "row", "flexDirection": "row",
"paddingHorizontal": 16, "paddingHorizontal": 16,
"paddingVertical": 10, "paddingVertical": 12,
}, },
undefined, undefined,
] ]
@ -322,13 +378,12 @@ exports[`render private group 1`] = `
Object { Object {
"alignItems": "center", "alignItems": "center",
"justifyContent": "center", "justifyContent": "center",
"overflow": "hidden",
}, },
Object { Object {
"backgroundColor": "#FF9800", "backgroundColor": "#FF9800",
"borderRadius": 4, "borderRadius": 4,
"height": 40, "height": 46,
"width": 40, "width": 46,
}, },
undefined, undefined,
] ]
@ -349,7 +404,7 @@ exports[`render private group 1`] = `
"color": "#ffffff", "color": "#ffffff",
}, },
Object { Object {
"fontSize": 20, "fontSize": 23,
}, },
], ],
Object { Object {
@ -367,44 +422,70 @@ exports[`render private group 1`] = `
style={ style={
Object { Object {
"flex": 1, "flex": 1,
"height": "100%",
"marginLeft": 16, "marginLeft": 16,
"marginRight": 4, "marginRight": 4,
} }
} }
> >
<Text <View
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 16,
},
undefined,
]
}
>
private-group
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={ style={
Object { Object {
"color": "#888", "alignItems": "center",
"flex": 1, "flex": 1,
"fontSize": 10, "flexDirection": "row",
"justifyContent": "center",
"width": "100%",
} }
} }
> >
Nov 10 <Text
</Text> accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 18,
"marginRight": 8,
},
undefined,
]
}
>
private-group
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Object {
"alignItems": "center",
"color": "#888",
"fontSize": 10,
"justifyContent": "center",
}
}
>
Nov 10
</Text>
</View>
<View
style={
Object {
"alignItems": "flex-end",
"flex": 1,
"flexDirection": "row",
"justifyContent": "flex-end",
"width": "100%",
}
}
/>
</View> </View>
</View> </View>
</View> </View>
@ -446,9 +527,11 @@ exports[`render unread +999 1`] = `
Array [ Array [
Object { Object {
"alignItems": "center", "alignItems": "center",
"borderBottomColor": "#ddd",
"borderBottomWidth": 0.5,
"flexDirection": "row", "flexDirection": "row",
"paddingHorizontal": 16, "paddingHorizontal": 16,
"paddingVertical": 10, "paddingVertical": 12,
}, },
undefined, undefined,
] ]
@ -460,13 +543,12 @@ exports[`render unread +999 1`] = `
Object { Object {
"alignItems": "center", "alignItems": "center",
"justifyContent": "center", "justifyContent": "center",
"overflow": "hidden",
}, },
Object { Object {
"backgroundColor": "#3F51B5", "backgroundColor": "#3F51B5",
"borderRadius": 4, "borderRadius": 4,
"height": 40, "height": 46,
"width": 40, "width": 46,
}, },
undefined, undefined,
] ]
@ -482,7 +564,7 @@ exports[`render unread +999 1`] = `
"color": "#ffffff", "color": "#ffffff",
}, },
Object { Object {
"fontSize": 20, "fontSize": 23,
}, },
] ]
} }
@ -490,70 +572,120 @@ exports[`render unread +999 1`] = `
NA NA
</Text> </Text>
<View
style={
Array [
Object {
"borderRadius": 16,
"height": 16,
"width": 16,
},
Object {
"borderColor": "#fff",
"borderWidth": 3,
"bottom": -3,
"position": "absolute",
"right": -3,
},
Object {
"backgroundColor": "#cbced1",
},
]
}
/>
</View> </View>
<View <View
style={ style={
Object { Object {
"flex": 1, "flex": 1,
"height": "100%",
"marginLeft": 16, "marginLeft": 16,
"marginRight": 4, "marginRight": 4,
} }
} }
> >
<Text <View
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 16,
},
undefined,
]
}
>
name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={ style={
Object { Object {
"color": "#888", "alignItems": "center",
"flex": 1, "flex": 1,
"fontSize": 10, "flexDirection": "row",
"justifyContent": "center",
"width": "100%",
} }
} }
> >
Nov 10 <Text
</Text> accessible={true}
</View> allowFontScaling={true}
<Text ellipsizeMode="tail"
accessible={true} numberOfLines={1}
allowFontScaling={true} style={
ellipsizeMode="tail" Array [
style={ Object {
Object { "color": "#444",
"backgroundColor": "#1d74f5", "flex": 1,
"borderRadius": 3, "fontSize": 18,
"color": "#fff", "marginRight": 8,
"fontSize": 14, },
"minWidth": 20, undefined,
"overflow": "hidden", ]
"paddingHorizontal": 5, }
"paddingVertical": 2, >
"textAlign": "center", name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Object {
"alignItems": "center",
"color": "#888",
"fontSize": 10,
"justifyContent": "center",
}
}
>
Nov 10
</Text>
</View>
<View
style={
Object {
"alignItems": "flex-end",
"flex": 1,
"flexDirection": "row",
"justifyContent": "flex-end",
"width": "100%",
}
} }
} >
> <Text
999+ accessible={true}
</Text> allowFontScaling={true}
ellipsizeMode="tail"
style={
Object {
"alignItems": "center",
"backgroundColor": "#1d74f5",
"borderRadius": 4,
"color": "#fff",
"fontSize": 14,
"justifyContent": "center",
"minWidth": 25,
"overflow": "hidden",
"paddingHorizontal": 5,
"paddingVertical": 4,
"textAlign": "center",
}
}
>
999+
</Text>
</View>
</View>
</View> </View>
</View> </View>
</View> </View>
@ -593,9 +725,11 @@ exports[`render unread 1`] = `
Array [ Array [
Object { Object {
"alignItems": "center", "alignItems": "center",
"borderBottomColor": "#ddd",
"borderBottomWidth": 0.5,
"flexDirection": "row", "flexDirection": "row",
"paddingHorizontal": 16, "paddingHorizontal": 16,
"paddingVertical": 10, "paddingVertical": 12,
}, },
undefined, undefined,
] ]
@ -607,13 +741,12 @@ exports[`render unread 1`] = `
Object { Object {
"alignItems": "center", "alignItems": "center",
"justifyContent": "center", "justifyContent": "center",
"overflow": "hidden",
}, },
Object { Object {
"backgroundColor": "#3F51B5", "backgroundColor": "#3F51B5",
"borderRadius": 4, "borderRadius": 4,
"height": 40, "height": 46,
"width": 40, "width": 46,
}, },
undefined, undefined,
] ]
@ -629,7 +762,7 @@ exports[`render unread 1`] = `
"color": "#ffffff", "color": "#ffffff",
}, },
Object { Object {
"fontSize": 20, "fontSize": 23,
}, },
] ]
} }
@ -637,70 +770,120 @@ exports[`render unread 1`] = `
NA NA
</Text> </Text>
<View
style={
Array [
Object {
"borderRadius": 16,
"height": 16,
"width": 16,
},
Object {
"borderColor": "#fff",
"borderWidth": 3,
"bottom": -3,
"position": "absolute",
"right": -3,
},
Object {
"backgroundColor": "#cbced1",
},
]
}
/>
</View> </View>
<View <View
style={ style={
Object { Object {
"flex": 1, "flex": 1,
"height": "100%",
"marginLeft": 16, "marginLeft": 16,
"marginRight": 4, "marginRight": 4,
} }
} }
> >
<Text <View
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 16,
},
undefined,
]
}
>
name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={ style={
Object { Object {
"color": "#888", "alignItems": "center",
"flex": 1, "flex": 1,
"fontSize": 10, "flexDirection": "row",
"justifyContent": "center",
"width": "100%",
} }
} }
> >
Nov 10 <Text
</Text> accessible={true}
</View> allowFontScaling={true}
<Text ellipsizeMode="tail"
accessible={true} numberOfLines={1}
allowFontScaling={true} style={
ellipsizeMode="tail" Array [
style={ Object {
Object { "color": "#444",
"backgroundColor": "#1d74f5", "flex": 1,
"borderRadius": 3, "fontSize": 18,
"color": "#fff", "marginRight": 8,
"fontSize": 14, },
"minWidth": 20, undefined,
"overflow": "hidden", ]
"paddingHorizontal": 5, }
"paddingVertical": 2, >
"textAlign": "center", name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Object {
"alignItems": "center",
"color": "#888",
"fontSize": 10,
"justifyContent": "center",
}
}
>
Nov 10
</Text>
</View>
<View
style={
Object {
"alignItems": "flex-end",
"flex": 1,
"flexDirection": "row",
"justifyContent": "flex-end",
"width": "100%",
}
} }
} >
> <Text
1 accessible={true}
</Text> allowFontScaling={true}
ellipsizeMode="tail"
style={
Object {
"alignItems": "center",
"backgroundColor": "#1d74f5",
"borderRadius": 4,
"color": "#fff",
"fontSize": 14,
"justifyContent": "center",
"minWidth": 25,
"overflow": "hidden",
"paddingHorizontal": 5,
"paddingVertical": 4,
"textAlign": "center",
}
}
>
1
</Text>
</View>
</View>
</View> </View>
</View> </View>
</View> </View>
@ -740,9 +923,11 @@ exports[`renders correctly 1`] = `
Array [ Array [
Object { Object {
"alignItems": "center", "alignItems": "center",
"borderBottomColor": "#ddd",
"borderBottomWidth": 0.5,
"flexDirection": "row", "flexDirection": "row",
"paddingHorizontal": 16, "paddingHorizontal": 16,
"paddingVertical": 10, "paddingVertical": 12,
}, },
undefined, undefined,
] ]
@ -754,13 +939,12 @@ exports[`renders correctly 1`] = `
Object { Object {
"alignItems": "center", "alignItems": "center",
"justifyContent": "center", "justifyContent": "center",
"overflow": "hidden",
}, },
Object { Object {
"backgroundColor": "#3F51B5", "backgroundColor": "#3F51B5",
"borderRadius": 4, "borderRadius": 4,
"height": 40, "height": 46,
"width": 40, "width": 46,
}, },
undefined, undefined,
] ]
@ -776,7 +960,7 @@ exports[`renders correctly 1`] = `
"color": "#ffffff", "color": "#ffffff",
}, },
Object { Object {
"fontSize": 20, "fontSize": 23,
}, },
] ]
} }
@ -784,49 +968,96 @@ exports[`renders correctly 1`] = `
NA NA
</Text> </Text>
<View
style={
Array [
Object {
"borderRadius": 16,
"height": 16,
"width": 16,
},
Object {
"borderColor": "#fff",
"borderWidth": 3,
"bottom": -3,
"position": "absolute",
"right": -3,
},
Object {
"backgroundColor": "#cbced1",
},
]
}
/>
</View> </View>
<View <View
style={ style={
Object { Object {
"flex": 1, "flex": 1,
"height": "100%",
"marginLeft": 16, "marginLeft": 16,
"marginRight": 4, "marginRight": 4,
} }
} }
> >
<Text <View
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 16,
},
undefined,
]
}
>
name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={ style={
Object { Object {
"color": "#888", "alignItems": "center",
"flex": 1, "flex": 1,
"fontSize": 10, "flexDirection": "row",
"justifyContent": "center",
"width": "100%",
} }
} }
> >
Nov 10 <Text
</Text> accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Array [
Object {
"color": "#444",
"flex": 1,
"fontSize": 18,
"marginRight": 8,
},
undefined,
]
}
>
name
</Text>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
numberOfLines={1}
style={
Object {
"alignItems": "center",
"color": "#888",
"fontSize": 10,
"justifyContent": "center",
}
}
>
Nov 10
</Text>
</View>
<View
style={
Object {
"alignItems": "flex-end",
"flex": 1,
"flexDirection": "row",
"justifyContent": "flex-end",
"width": "100%",
}
}
/>
</View> </View>
</View> </View>
</View> </View>

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,4 +1,4 @@
package com.rocketchatrn; package chat.rocket.reactnative;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;

View File

@ -1,4 +1,4 @@
package com.rocketchatrn; package chat.rocket.reactnative;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;

View File

@ -44,7 +44,8 @@ public class MainApplication extends Application implements ReactApplication {
new ReactVideoPackage(), new ReactVideoPackage(),
new SplashScreenReactPackage(), new SplashScreenReactPackage(),
new RCTToastPackage(), new RCTToastPackage(),
new KeyboardInputPackage(MainApplication.this) new KeyboardInputPackage(MainApplication.this),
new RocketChatNativePackage()
); );
} }
}; };

View File

@ -1,4 +1,4 @@
package com.rocketchatrn; package chat.rocket.reactnative;
import com.facebook.react.ReactPackage; import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.JavaScriptModule;

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

@ -18,6 +18,7 @@ import {
} from '../actions/messages'; } from '../actions/messages';
import { showToast } from '../utils/info'; import { showToast } from '../utils/info';
const returnAnArray = obj => obj || [];
@connect( @connect(
state => ({ state => ({
showActions: state.messages.showActions, showActions: state.messages.showActions,
@ -171,11 +172,11 @@ export default class MessageActions extends React.Component {
} }
setPermissions(permissions) { setPermissions(permissions) {
this.hasEditPermission = permissions['edit-message'] this.hasEditPermission = returnAnArray(permissions['edit-message'])
.some(item => this.mergedRoles.indexOf(item) !== -1); .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); .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); .some(item => this.mergedRoles.indexOf(item) !== -1);
} }

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Text, StyleSheet } from 'react-native'; import { Text, StyleSheet, ViewPropTypes } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import EasyMarkdown from 'react-native-easy-markdown'; // eslint-disable-line import EasyMarkdown from 'react-native-easy-markdown'; // eslint-disable-line
import SimpleMarkdown from 'simple-markdown'; import SimpleMarkdown from 'simple-markdown';
@ -17,13 +17,15 @@ const BlockCode = ({ node, state }) => (
); );
const mentionStyle = { color: '#13679a' }; const mentionStyle = { color: '#13679a' };
const Markdown = ({ msg, customEmojis }) => { const Markdown = ({
msg, customEmojis, style, markdownStyle, customRules, renderInline
}) => {
if (!msg) { if (!msg) {
return null; return null;
} }
msg = emojify(msg, { output: 'unicode' }); msg = emojify(msg, { output: 'unicode' });
const rules = { const defaultRules = {
username: { username: {
order: -1, order: -1,
match: SimpleMarkdown.inlineRegex(/^@[0-9a-zA-Z-_.]+/), match: SimpleMarkdown.inlineRegex(/^@[0-9a-zA-Z-_.]+/),
@ -121,11 +123,13 @@ const Markdown = ({ msg, customEmojis }) => {
}; };
const codeStyle = StyleSheet.flatten(styles.codeStyle); const codeStyle = StyleSheet.flatten(styles.codeStyle);
style = StyleSheet.flatten(style);
return ( return (
<EasyMarkdown <EasyMarkdown
style={{ marginBottom: 0 }} style={{ marginBottom: 0, ...style }}
rules={rules} markdownStyles={{ code: codeStyle, ...markdownStyle }}
markdownStyles={{ code: codeStyle }} rules={{ ...defaultRules, ...customRules }}
renderInline={renderInline}
>{msg} >{msg}
</EasyMarkdown> </EasyMarkdown>
); );
@ -133,7 +137,12 @@ const Markdown = ({ msg, customEmojis }) => {
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,
markdownStyle: PropTypes.object,
customRules: PropTypes.object,
renderInline: PropTypes.bool
}; };
BlockCode.propTypes = { BlockCode.propTypes = {

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 && this.props.activeUsers[userId]) || 'offline';
}
render() {
return (<View style={[styles.status, this.props.style, { backgroundColor: STATUS_COLORS[this.status] }]} />);
}
}

View File

@ -49,6 +49,7 @@ const roomsSchema = {
properties: { properties: {
_id: 'string', _id: 'string',
t: 'string', t: 'string',
lastMessage: 'messages',
_updatedAt: { type: 'date', optional: true } _updatedAt: { type: 'date', optional: true }
} }
}; };
@ -80,7 +81,8 @@ const subscriptionSchema = {
// userMentions: 0, // userMentions: 0,
// groupMentions: 0, // groupMentions: 0,
roomUpdatedAt: { type: 'date', optional: true }, 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 = { const url = {
name: 'url', name: 'url',
properties: { properties: {
_id: 'int', // _id: { type: 'int', optional: true },
url: { type: 'string', optional: true }, url: { type: 'string', optional: true },
title: { type: 'string', optional: true }, title: { type: 'string', optional: true },
description: { type: 'string', optional: true }, description: { type: 'string', optional: true },
@ -183,7 +185,7 @@ const messagesSchema = {
groupable: { type: 'bool', optional: true }, groupable: { type: 'bool', optional: true },
avatar: { type: 'string', optional: true }, avatar: { type: 'string', optional: true },
attachments: { type: 'list', objectType: 'attachment' }, attachments: { type: 'list', objectType: 'attachment' },
urls: { type: 'list', objectType: 'url' }, urls: { type: 'list', objectType: 'url', default: [] },
_updatedAt: { type: 'date', optional: true }, _updatedAt: { type: 'date', optional: true },
status: { type: 'int', optional: true }, status: { type: 'int', optional: true },
pinned: { type: 'bool', optional: true }, pinned: { type: 'bool', optional: true },

View File

@ -128,11 +128,12 @@ const RocketChat = {
const sub = database.objects('subscriptions').filtered('rid == $0', data._id)[0]; const sub = database.objects('subscriptions').filtered('rid == $0', data._id)[0];
database.write(() => { database.write(() => {
sub.roomUpdatedAt = data._updatedAt; sub.roomUpdatedAt = data._updatedAt;
sub.lastMessage = data.lastMessage;
sub.ro = data.ro; sub.ro = data.ro;
}); });
} }
}); });
}); }).catch(console.log);
}, },
me({ server, token, userId }) { me({ server, token, userId }) {
@ -428,6 +429,7 @@ const RocketChat = {
const room = rooms.find(({ _id }) => _id === subscription.rid); const room = rooms.find(({ _id }) => _id === subscription.rid);
if (room) { if (room) {
subscription.roomUpdatedAt = room._updatedAt; subscription.roomUpdatedAt = room._updatedAt;
subscription.lastMessage = room.lastMessage;
subscription.ro = room.ro; subscription.ro = room.ro;
} }
if (subscription.roles) { if (subscription.roles) {
@ -435,10 +437,14 @@ const RocketChat = {
} }
return subscription; return subscription;
}); });
database.write(() => { database.write(() => {
data.forEach(subscription => data.forEach(subscription => database.create('subscriptions', subscription, true));
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 }/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);
return data; return data;

View File

@ -2,36 +2,60 @@ 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 { connect } from 'react-redux';
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';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flexDirection: 'row', flexDirection: 'row',
paddingHorizontal: 16, paddingHorizontal: 16,
paddingVertical: 10, paddingVertical: 12,
alignItems: 'center' alignItems: 'center',
borderBottomWidth: 0.5,
borderBottomColor: '#ddd'
}, },
number: { number: {
minWidth: 20, minWidth: 25,
borderRadius: 3, borderRadius: 4,
backgroundColor: '#1d74f5', backgroundColor: '#1d74f5',
color: '#fff', color: '#fff',
textAlign: 'center',
overflow: 'hidden', overflow: 'hidden',
fontSize: 14, fontSize: 14,
paddingVertical: 4,
paddingHorizontal: 5, paddingHorizontal: 5,
paddingVertical: 2
textAlign: 'center',
alignItems: 'center',
justifyContent: 'center'
}, },
roomNameView: { roomNameView: {
flex: 1, flex: 1,
height: '100%',
marginLeft: 16, marginLeft: 16,
marginRight: 4 marginRight: 4
}, },
roomName: { roomName: {
flex: 1, flex: 1,
fontSize: 16, fontSize: 18,
color: '#444' color: '#444',
marginRight: 8
},
lastMessage: {
flex: 1,
flexShrink: 1,
marginRight: 8,
maxHeight: 20,
overflow: 'hidden',
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'flex-start'
}, },
alert: { alert: {
fontWeight: 'bold' fontWeight: 'bold'
@ -39,30 +63,144 @@ const styles = StyleSheet.create({
favorite: { favorite: {
// backgroundColor: '#eee' // backgroundColor: '#eee'
}, },
update: { row: {
width: '100%',
flex: 1, flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'flex-end'
},
firstRow: {
width: '100%',
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
},
update: {
fontSize: 10, 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 (
<Text style={styles.number}>
{ unread }
</Text>
);
};
@connect(state => ({
user: state.login && state.login.user,
StoreLastMessage: state.settings.Store_Last_Message,
customEmojis: state.customEmojis
}))
export default class RoomItem extends React.PureComponent { export default class RoomItem extends React.PureComponent {
static propTypes = { static propTypes = {
type: PropTypes.string.isRequired, type: PropTypes.string.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
StoreLastMessage: PropTypes.bool,
_updatedAt: PropTypes.instanceOf(Date), _updatedAt: PropTypes.instanceOf(Date),
lastMessage: PropTypes.object,
favorite: PropTypes.bool, favorite: PropTypes.bool,
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,
user: PropTypes.object
} }
get icon() { get icon() {
const { type, name, baseUrl } = this.props; const {
return <Avatar text={name} baseUrl={baseUrl} size={40} 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() {
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, { formatDate = date => moment(date).calendar(null, {
@ -72,29 +210,9 @@ export default class RoomItem extends React.PureComponent {
sameElse: 'MMM D' sameElse: 'MMM D'
}) })
renderNumber = (unread, userMentions) => {
if (!unread || unread <= 0) {
return;
}
if (unread >= 1000) {
unread = '999+';
}
if (userMentions > 0) {
unread = `@ ${ unread }`;
}
return (
<Text style={styles.number}>
{ unread }
</Text>
);
}
render() { render() {
const { const {
favorite, alert, unread, userMentions, name, _updatedAt favorite, unread, userMentions, name, _updatedAt, customEmojis, alert
} = this.props; } = this.props;
const date = this.formatDate(_updatedAt); const date = this.formatDate(_updatedAt);
@ -117,10 +235,23 @@ 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}>
<Text style={[styles.roomName, alert && styles.alert]} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text> <View style={styles.firstRow}>
{_updatedAt ? <Text style={styles.update} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null} <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}
</View>
<View style={styles.row}>
<Markdown
msg={this.lastMessage}
customEmojis={customEmojis}
style={styles.lastMessage}
markdownStyle={markdownStyle}
customRules={customRules}
renderInline
numberOfLines={1}
/>
{renderNumber(unread, userMentions)}
</View>
</View> </View>
{this.renderNumber(unread, userMentions)}
</View> </View>
</Touch> </Touch>
); );

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; 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 { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import equal from 'deep-equal'; import equal from 'deep-equal';
@ -51,8 +51,8 @@ export default class RoomView extends React.Component {
Message_TimeFormat: PropTypes.string, Message_TimeFormat: PropTypes.string,
loading: PropTypes.bool, loading: PropTypes.bool,
actionMessage: PropTypes.object, actionMessage: PropTypes.object,
toggleReactionPicker: PropTypes.func.isRequired, toggleReactionPicker: PropTypes.func.isRequired
layoutAnimation: PropTypes.instanceOf(Date) // layoutAnimation: PropTypes.instanceOf(Date)
}; };
static navigationOptions = ({ navigation }) => ({ static navigationOptions = ({ navigation }) => ({
@ -90,11 +90,11 @@ export default class RoomView extends React.Component {
this.rooms.addListener(this.updateRoom); this.rooms.addListener(this.updateRoom);
} }
componentWillReceiveProps(nextProps) { // componentWillReceiveProps(nextProps) {
if (this.props.layoutAnimation !== nextProps.layoutAnimation) { // // if (this.props.layoutAnimation !== nextProps.layoutAnimation) {
LayoutAnimation.spring(); // // LayoutAnimation.spring();
} // // }
} // }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
return !(equal(this.props, nextProps) && equal(this.state, nextState)); return !(equal(this.props, nextProps) && equal(this.state, nextState));
} }

View File

@ -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,7 +71,9 @@ export default class RoomsListView extends React.Component {
this.search(props.searchText); this.search(props.searchText);
} }
} }
// componentWillUpdate() {
// LayoutAnimation.easeInEaseOut();
// }
componentWillUnmount() { componentWillUnmount() {
this.data.removeAllListeners(); this.data.removeAllListeners();
} }
@ -79,6 +83,12 @@ export default class RoomsListView extends React.Component {
this.search(text); 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) { search(text) {
const searchText = text.trim(); const searchText = text.trim();
if (searchText === '') { if (searchText === '') {
@ -197,20 +207,23 @@ 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}
favorite={item.f} favorite={item.f}
lastMessage={item.lastMessage}
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

2
package-lock.json generated
View File

@ -12505,7 +12505,7 @@
} }
}, },
"react-native-easy-markdown": { "react-native-easy-markdown": {
"version": "git+https://github.com/diegolmello/react-native-easy-markdown.git#ed1afe45f870524f6c23a4ca1df97770f0979c74", "version": "git+https://github.com/diegolmello/react-native-easy-markdown.git#600a79faf4fdac2c21cfebeb01f96b997674dabe",
"requires": { "requires": {
"simple-markdown": "0.1.2" "simple-markdown": "0.1.2"
}, },