[NEW] Room actions: Mentioned messages and Room Members (#242)
* Mentioned messages * Starred and pinned actions debounce * Room members * Open room on member touch
This commit is contained in:
parent
477609375c
commit
4823e3a2e4
|
@ -37,6 +37,7 @@ module.exports = {
|
||||||
"react/no-unused-prop-types": [2, {
|
"react/no-unused-prop-types": [2, {
|
||||||
"skipShapeProps": true
|
"skipShapeProps": true
|
||||||
}],
|
}],
|
||||||
|
"react/no-did-mount-set-state": 0,
|
||||||
"react/no-multi-comp": [0],
|
"react/no-multi-comp": [0],
|
||||||
"react/jsx-indent": [2, "tab"],
|
"react/jsx-indent": [2, "tab"],
|
||||||
"react/jsx-indent-props": [2, "tab"],
|
"react/jsx-indent-props": [2, "tab"],
|
||||||
|
|
|
@ -136,12 +136,15 @@ exports[`render channel 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -300,12 +303,15 @@ exports[`render no icon 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -464,12 +470,15 @@ exports[`render private group 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -640,12 +649,15 @@ exports[`render unread +999 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -838,12 +850,15 @@ exports[`render unread 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1036,12 +1051,15 @@ exports[`renders correctly 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
|
|
@ -299,12 +299,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -471,12 +474,17 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"color": "#1d74f5",
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -641,12 +649,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -836,12 +847,17 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"color": "#1d74f5",
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1029,12 +1045,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1222,12 +1241,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1415,12 +1437,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1608,12 +1633,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1801,12 +1829,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -1971,12 +2002,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
@ -2141,12 +2175,15 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={
|
style={
|
||||||
Object {
|
Array [
|
||||||
"alignItems": "center",
|
Object {
|
||||||
"color": "#888",
|
"alignItems": "center",
|
||||||
"fontSize": 10,
|
"color": "#888",
|
||||||
"justifyContent": "center",
|
"fontSize": 10,
|
||||||
}
|
"justifyContent": "center",
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Nov 10
|
Nov 10
|
||||||
|
|
|
@ -93,8 +93,9 @@ export const SERVER = createRequestTypes('SERVER', [
|
||||||
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']);
|
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT', 'DISCONNECT_BY_USER']);
|
||||||
export const LOGOUT = 'LOGOUT'; // logout is always success
|
export const LOGOUT = 'LOGOUT'; // logout is always success
|
||||||
export const ACTIVE_USERS = createRequestTypes('ACTIVE_USERS', ['SET', 'REQUEST']);
|
export const ACTIVE_USERS = createRequestTypes('ACTIVE_USERS', ['SET', 'REQUEST']);
|
||||||
export const STARRED_MESSAGES = createRequestTypes('STARRED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGE_RECEIVED', 'MESSAGE_UNSTARRED']);
|
export const STARRED_MESSAGES = createRequestTypes('STARRED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED', 'MESSAGE_UNSTARRED']);
|
||||||
export const PINNED_MESSAGES = createRequestTypes('PINNED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGE_RECEIVED', 'MESSAGE_UNPINNED']);
|
export const PINNED_MESSAGES = createRequestTypes('PINNED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED', 'MESSAGE_UNPINNED']);
|
||||||
|
export const MENTIONED_MESSAGES = createRequestTypes('MENTIONED_MESSAGES', ['OPEN', 'CLOSE', 'MESSAGES_RECEIVED']);
|
||||||
|
|
||||||
export const INCREMENT = 'INCREMENT';
|
export const INCREMENT = 'INCREMENT';
|
||||||
export const DECREMENT = 'DECREMENT';
|
export const DECREMENT = 'DECREMENT';
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export function openMentionedMessages(rid) {
|
||||||
|
return {
|
||||||
|
type: types.MENTIONED_MESSAGES.OPEN,
|
||||||
|
rid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeMentionedMessages() {
|
||||||
|
return {
|
||||||
|
type: types.MENTIONED_MESSAGES.CLOSE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mentionedMessagesReceived(messages) {
|
||||||
|
return {
|
||||||
|
type: types.MENTIONED_MESSAGES.MESSAGES_RECEIVED,
|
||||||
|
messages
|
||||||
|
};
|
||||||
|
}
|
|
@ -13,10 +13,10 @@ export function closePinnedMessages() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pinnedMessageReceived(message) {
|
export function pinnedMessagesReceived(messages) {
|
||||||
return {
|
return {
|
||||||
type: types.PINNED_MESSAGES.MESSAGE_RECEIVED,
|
type: types.PINNED_MESSAGES.MESSAGES_RECEIVED,
|
||||||
message
|
messages
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,10 @@ export function closeStarredMessages() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function starredMessageReceived(message) {
|
export function starredMessagesReceived(messages) {
|
||||||
return {
|
return {
|
||||||
type: types.STARRED_MESSAGES.MESSAGE_RECEIVED,
|
type: types.STARRED_MESSAGES.MESSAGES_RECEIVED,
|
||||||
message
|
messages
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ const Reply = ({ attachment, timeFormat }) => {
|
||||||
{renderTitle()}
|
{renderTitle()}
|
||||||
{renderText()}
|
{renderText()}
|
||||||
{renderFields()}
|
{renderFields()}
|
||||||
{attachment.attachments.map(attach => <Reply key={attach.text} attachment={attach} timeFormat={timeFormat} />)}
|
{attachment.attachments && attachment.attachments.map(attach => <Reply key={attach.text} attachment={attach} timeFormat={timeFormat} />)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { View, TouchableHighlight, Text, TouchableOpacity, Vibration, ViewPropTy
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import equal from 'deep-equal';
|
// import equal from 'deep-equal';
|
||||||
import { KeyboardUtils } from 'react-native-keyboard-input';
|
import { KeyboardUtils } from 'react-native-keyboard-input';
|
||||||
|
|
||||||
import { actionsShow, errorActionsShow, toggleReactionPicker } from '../../actions/messages';
|
import { actionsShow, errorActionsShow, toggleReactionPicker } from '../../actions/messages';
|
||||||
|
@ -52,22 +52,16 @@ export default class Message extends React.Component {
|
||||||
this.state = { reactionsModal: false };
|
this.state = { reactionsModal: false };
|
||||||
this.onClose = this.onClose.bind(this);
|
this.onClose = this.onClose.bind(this);
|
||||||
}
|
}
|
||||||
componentWillReceiveProps() {
|
|
||||||
this.extraStyle = this.extraStyle || {};
|
|
||||||
if (this.props.item.status === messageStatus.TEMP || this.props.item.status === messageStatus.ERROR) {
|
|
||||||
this.extraStyle.opacity = 0.3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
// shouldComponentUpdate(nextProps, nextState) {
|
||||||
if (!equal(this.props.reactions, nextProps.reactions)) {
|
// if (!equal(this.props.reactions, nextProps.reactions)) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
if (this.state.reactionsModal !== nextState.reactionsModal) {
|
// if (this.state.reactionsModal !== nextState.reactionsModal) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
return this.props.item._updatedAt.toGMTString() !== nextProps.item._updatedAt.toGMTString() || this.props.item.status !== nextProps.item.status;
|
// return this.props.item._updatedAt.toGMTString() !== nextProps.item._updatedAt.toGMTString() || this.props.item.status !== nextProps.item.status;
|
||||||
}
|
// }
|
||||||
|
|
||||||
onPress = () => {
|
onPress = () => {
|
||||||
KeyboardUtils.dismiss();
|
KeyboardUtils.dismiss();
|
||||||
|
@ -129,6 +123,10 @@ export default class Message extends React.Component {
|
||||||
return this.props.item.t === 'rm';
|
return this.props.item.t === 'rm';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isTemp() {
|
||||||
|
return this.props.item.status === messageStatus.TEMP || this.props.item.status === messageStatus.ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
hasError() {
|
hasError() {
|
||||||
return this.props.item.status === messageStatus.ERROR;
|
return this.props.item.status === messageStatus.ERROR;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +239,7 @@ export default class Message extends React.Component {
|
||||||
>
|
>
|
||||||
<View style={styles.flex}>
|
<View style={styles.flex}>
|
||||||
{this.renderError()}
|
{this.renderError()}
|
||||||
<View style={[this.extraStyle, styles.flex]}>
|
<View style={[this.isTemp() && { opacity: 0.3 }, styles.flex]}>
|
||||||
<Avatar
|
<Avatar
|
||||||
style={styles.avatar}
|
style={styles.avatar}
|
||||||
text={item.avatar ? '' : username}
|
text={item.avatar ? '' : username}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import SelectUsersView from '../../views/SelectUsersView';
|
||||||
import NewServerView from '../../views/NewServerView';
|
import NewServerView from '../../views/NewServerView';
|
||||||
import StarredMessagesView from '../../views/StarredMessagesView';
|
import StarredMessagesView from '../../views/StarredMessagesView';
|
||||||
import PinnedMessagesView from '../../views/PinnedMessagesView';
|
import PinnedMessagesView from '../../views/PinnedMessagesView';
|
||||||
|
import MentionedMessagesView from '../../views/MentionedMessagesView';
|
||||||
|
import RoomMembersView from '../../views/RoomMembersView';
|
||||||
|
|
||||||
const AuthRoutes = StackNavigator(
|
const AuthRoutes = StackNavigator(
|
||||||
{
|
{
|
||||||
|
@ -57,6 +59,20 @@ const AuthRoutes = StackNavigator(
|
||||||
title: 'Pinned Messages',
|
title: 'Pinned Messages',
|
||||||
headerTintColor: '#292E35'
|
headerTintColor: '#292E35'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
MentionedMessages: {
|
||||||
|
screen: MentionedMessagesView,
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Mentioned Messages',
|
||||||
|
headerTintColor: '#292E35'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RoomMembers: {
|
||||||
|
screen: RoomMembersView,
|
||||||
|
navigationOptions: {
|
||||||
|
title: 'Room Members',
|
||||||
|
headerTintColor: '#292E35'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ const settingsSchema = {
|
||||||
|
|
||||||
const permissionsRolesSchema = {
|
const permissionsRolesSchema = {
|
||||||
name: 'permissionsRoles',
|
name: 'permissionsRoles',
|
||||||
|
primaryKey: 'value',
|
||||||
properties: {
|
properties: {
|
||||||
value: 'string'
|
value: 'string'
|
||||||
}
|
}
|
||||||
|
@ -56,6 +57,7 @@ const roomsSchema = {
|
||||||
|
|
||||||
const subscriptionRolesSchema = {
|
const subscriptionRolesSchema = {
|
||||||
name: 'subscriptionRolesSchema',
|
name: 'subscriptionRolesSchema',
|
||||||
|
primaryKey: 'value',
|
||||||
properties: {
|
properties: {
|
||||||
value: 'string'
|
value: 'string'
|
||||||
}
|
}
|
||||||
|
@ -70,9 +72,9 @@ const subscriptionSchema = {
|
||||||
t: 'string',
|
t: 'string',
|
||||||
ts: { type: 'date', optional: true },
|
ts: { type: 'date', optional: true },
|
||||||
ls: { type: 'date', optional: true },
|
ls: { type: 'date', optional: true },
|
||||||
name: 'string',
|
name: { type: 'string', indexed: true },
|
||||||
fname: { type: 'string', optional: true },
|
fname: { type: 'string', optional: true },
|
||||||
rid: 'string',
|
rid: { type: 'string', indexed: true },
|
||||||
open: { type: 'bool', optional: true },
|
open: { type: 'bool', optional: true },
|
||||||
alert: { type: 'bool', optional: true },
|
alert: { type: 'bool', optional: true },
|
||||||
roles: { type: 'list', objectType: 'subscriptionRolesSchema' },
|
roles: { type: 'list', objectType: 'subscriptionRolesSchema' },
|
||||||
|
@ -83,7 +85,10 @@ const subscriptionSchema = {
|
||||||
roomUpdatedAt: { type: 'date', optional: true },
|
roomUpdatedAt: { type: 'date', optional: true },
|
||||||
ro: { type: 'bool', optional: true },
|
ro: { type: 'bool', optional: true },
|
||||||
lastOpen: { type: 'date', optional: true },
|
lastOpen: { type: 'date', optional: true },
|
||||||
lastMessage: { type: 'messages', optional: true }
|
lastMessage: { type: 'messages', optional: true },
|
||||||
|
description: { type: 'string', optional: true },
|
||||||
|
announcement: { type: 'string', optional: true },
|
||||||
|
topic: { type: 'string', optional: true }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,6 +141,7 @@ const attachment = {
|
||||||
|
|
||||||
const url = {
|
const url = {
|
||||||
name: 'url',
|
name: 'url',
|
||||||
|
primaryKey: 'url',
|
||||||
properties: {
|
properties: {
|
||||||
// _id: { type: 'int', optional: true },
|
// _id: { type: 'int', optional: true },
|
||||||
url: { type: 'string', optional: true },
|
url: { type: 'string', optional: true },
|
||||||
|
@ -147,6 +153,7 @@ const url = {
|
||||||
|
|
||||||
const messagesReactionsUsernamesSchema = {
|
const messagesReactionsUsernamesSchema = {
|
||||||
name: 'messagesReactionsUsernames',
|
name: 'messagesReactionsUsernames',
|
||||||
|
primaryKey: 'value',
|
||||||
properties: {
|
properties: {
|
||||||
value: 'string'
|
value: 'string'
|
||||||
}
|
}
|
||||||
|
@ -163,6 +170,7 @@ const messagesReactionsSchema = {
|
||||||
|
|
||||||
const messagesEditedBySchema = {
|
const messagesEditedBySchema = {
|
||||||
name: 'messagesEditedBy',
|
name: 'messagesEditedBy',
|
||||||
|
primaryKey: '_id',
|
||||||
properties: {
|
properties: {
|
||||||
_id: { type: 'string', optional: true },
|
_id: { type: 'string', optional: true },
|
||||||
username: { type: 'string', optional: true }
|
username: { type: 'string', optional: true }
|
||||||
|
@ -176,7 +184,7 @@ const messagesSchema = {
|
||||||
_id: 'string',
|
_id: 'string',
|
||||||
msg: { type: 'string', optional: true },
|
msg: { type: 'string', optional: true },
|
||||||
t: { type: 'string', optional: true },
|
t: { type: 'string', optional: true },
|
||||||
rid: 'string',
|
rid: { type: 'string', indexed: true },
|
||||||
ts: 'date',
|
ts: 'date',
|
||||||
u: 'users',
|
u: 'users',
|
||||||
// mentions: [],
|
// mentions: [],
|
||||||
|
@ -209,6 +217,7 @@ const frequentlyUsedEmojiSchema = {
|
||||||
|
|
||||||
const customEmojiAliasesSchema = {
|
const customEmojiAliasesSchema = {
|
||||||
name: 'customEmojiAliases',
|
name: 'customEmojiAliases',
|
||||||
|
primaryKey: 'value',
|
||||||
properties: {
|
properties: {
|
||||||
value: 'string'
|
value: 'string'
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,9 @@ import { someoneTyping, roomMessageReceived } from '../actions/room';
|
||||||
import { setUser, setLoginServices, removeLoginServices } from '../actions/login';
|
import { setUser, setLoginServices, removeLoginServices } from '../actions/login';
|
||||||
import { disconnect, disconnect_by_user, connectSuccess, connectFailure } from '../actions/connect';
|
import { disconnect, disconnect_by_user, connectSuccess, connectFailure } from '../actions/connect';
|
||||||
import { requestActiveUser } from '../actions/activeUsers';
|
import { requestActiveUser } from '../actions/activeUsers';
|
||||||
import { starredMessageReceived, starredMessageUnstarred } from '../actions/starredMessages';
|
import { starredMessagesReceived, starredMessageUnstarred } from '../actions/starredMessages';
|
||||||
import { pinnedMessageReceived, pinnedMessageUnpinned } from '../actions/pinnedMessages';
|
import { pinnedMessagesReceived, pinnedMessageUnpinned } from '../actions/pinnedMessages';
|
||||||
|
import { mentionedMessagesReceived } from '../actions/mentionedMessages';
|
||||||
import Ddp from './ddp';
|
import Ddp from './ddp';
|
||||||
|
|
||||||
export { Accounts } from 'react-native-meteor';
|
export { Accounts } from 'react-native-meteor';
|
||||||
|
@ -64,7 +65,7 @@ const RocketChat = {
|
||||||
const status = (ddpMessage.fields && ddpMessage.fields.status) || 'offline';
|
const status = (ddpMessage.fields && ddpMessage.fields.status) || 'offline';
|
||||||
|
|
||||||
if (user && user.id === ddpMessage.id) {
|
if (user && user.id === ddpMessage.id) {
|
||||||
return reduxStore.dispatch(setUser({ status }));
|
reduxStore.dispatch(setUser({ status }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._setUserTimer) {
|
if (this._setUserTimer) {
|
||||||
|
@ -153,25 +154,74 @@ const RocketChat = {
|
||||||
|
|
||||||
this.ddp.on('rocketchat_starred_message', (ddpMessage) => {
|
this.ddp.on('rocketchat_starred_message', (ddpMessage) => {
|
||||||
if (ddpMessage.msg === 'added') {
|
if (ddpMessage.msg === 'added') {
|
||||||
|
this.starredMessages = this.starredMessages || [];
|
||||||
|
|
||||||
|
if (this.starredMessagesTimer) {
|
||||||
|
clearTimeout(this.starredMessagesTimer);
|
||||||
|
this.starredMessagesTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.starredMessagesTimer = setTimeout(() => {
|
||||||
|
reduxStore.dispatch(starredMessagesReceived(this.starredMessages));
|
||||||
|
this.starredMessagesTimer = null;
|
||||||
|
return this.starredMessages = [];
|
||||||
|
}, 1000);
|
||||||
const message = ddpMessage.fields;
|
const message = ddpMessage.fields;
|
||||||
message._id = ddpMessage.id;
|
message._id = ddpMessage.id;
|
||||||
const starredMessage = this._buildMessage(message);
|
const starredMessage = this._buildMessage(message);
|
||||||
return reduxStore.dispatch(starredMessageReceived(starredMessage));
|
this.starredMessages = [...this.starredMessages, starredMessage];
|
||||||
}
|
}
|
||||||
if (ddpMessage.msg === 'removed') {
|
if (ddpMessage.msg === 'removed') {
|
||||||
return reduxStore.dispatch(starredMessageUnstarred(ddpMessage.id));
|
if (reduxStore.getState().starredMessages.isOpen) {
|
||||||
|
return reduxStore.dispatch(starredMessageUnstarred(ddpMessage.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ddp.on('rocketchat_pinned_message', (ddpMessage) => {
|
this.ddp.on('rocketchat_pinned_message', (ddpMessage) => {
|
||||||
if (ddpMessage.msg === 'added') {
|
if (ddpMessage.msg === 'added') {
|
||||||
|
this.pinnedMessages = this.pinnedMessages || [];
|
||||||
|
|
||||||
|
if (this.pinnedMessagesTimer) {
|
||||||
|
clearTimeout(this.pinnedMessagesTimer);
|
||||||
|
this.pinnedMessagesTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pinnedMessagesTimer = setTimeout(() => {
|
||||||
|
reduxStore.dispatch(pinnedMessagesReceived(this.pinnedMessages));
|
||||||
|
this.pinnedMessagesTimer = null;
|
||||||
|
return this.pinnedMessages = [];
|
||||||
|
}, 1000);
|
||||||
const message = ddpMessage.fields;
|
const message = ddpMessage.fields;
|
||||||
message._id = ddpMessage.id;
|
message._id = ddpMessage.id;
|
||||||
const pinnedMessage = this._buildMessage(message);
|
const pinnedMessage = this._buildMessage(message);
|
||||||
return reduxStore.dispatch(pinnedMessageReceived(pinnedMessage));
|
this.pinnedMessages = [...this.pinnedMessages, pinnedMessage];
|
||||||
}
|
}
|
||||||
if (ddpMessage.msg === 'removed') {
|
if (ddpMessage.msg === 'removed') {
|
||||||
return reduxStore.dispatch(pinnedMessageUnpinned(ddpMessage.id));
|
if (reduxStore.getState().pinnedMessages.isOpen) {
|
||||||
|
return reduxStore.dispatch(pinnedMessageUnpinned(ddpMessage.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ddp.on('rocketchat_mentioned_message', (ddpMessage) => {
|
||||||
|
if (ddpMessage.msg === 'added') {
|
||||||
|
this.mentionedMessages = this.mentionedMessages || [];
|
||||||
|
|
||||||
|
if (this.mentionedMessagesTimer) {
|
||||||
|
clearTimeout(this.mentionedMessagesTimer);
|
||||||
|
this.mentionedMessagesTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mentionedMessagesTimer = setTimeout(() => {
|
||||||
|
reduxStore.dispatch(mentionedMessagesReceived(this.mentionedMessages));
|
||||||
|
this.mentionedMessagesTimer = null;
|
||||||
|
return this.mentionedMessages = [];
|
||||||
|
}, 1000);
|
||||||
|
const message = ddpMessage.fields;
|
||||||
|
message._id = ddpMessage.id;
|
||||||
|
const mentionedMessage = this._buildMessage(message);
|
||||||
|
this.mentionedMessages = [...this.mentionedMessages, mentionedMessage];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -324,6 +374,7 @@ const RocketChat = {
|
||||||
message.status = messagesStatus.SENT;
|
message.status = messagesStatus.SENT;
|
||||||
normalizeMessage(message);
|
normalizeMessage(message);
|
||||||
message.urls = message.urls ? RocketChat._parseUrls(message.urls) : [];
|
message.urls = message.urls ? RocketChat._parseUrls(message.urls) : [];
|
||||||
|
message._updatedAt = new Date();
|
||||||
// loadHistory returns message.starred as object
|
// loadHistory returns message.starred as object
|
||||||
// stream-room-messages returns message.starred as an array
|
// stream-room-messages returns message.starred as an array
|
||||||
message.starred = message.starred && (Array.isArray(message.starred) ? message.starred.length > 0 : !!message.starred);
|
message.starred = message.starred && (Array.isArray(message.starred) ? message.starred.length > 0 : !!message.starred);
|
||||||
|
@ -497,6 +548,9 @@ const RocketChat = {
|
||||||
subscription.roomUpdatedAt = room._updatedAt;
|
subscription.roomUpdatedAt = room._updatedAt;
|
||||||
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
subscription.lastMessage = normalizeMessage(room.lastMessage);
|
||||||
subscription.ro = room.ro;
|
subscription.ro = room.ro;
|
||||||
|
subscription.description = room.description;
|
||||||
|
subscription.topic = room.topic;
|
||||||
|
subscription.announcement = room.announcement;
|
||||||
}
|
}
|
||||||
if (subscription.roles) {
|
if (subscription.roles) {
|
||||||
subscription.roles = subscription.roles.map(role => ({ value: role }));
|
subscription.roles = subscription.roles.map(role => ({ value: role }));
|
||||||
|
@ -667,6 +721,9 @@ const RocketChat = {
|
||||||
},
|
},
|
||||||
toggleFavorite(rid, f) {
|
toggleFavorite(rid, f) {
|
||||||
return call('toggleFavorite', rid, !f);
|
return call('toggleFavorite', rid, !f);
|
||||||
|
},
|
||||||
|
getRoomMembers(rid, allUsers) {
|
||||||
|
return call('getUsersOfRoom', rid, allUsers);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,9 @@ const styles = StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
},
|
},
|
||||||
|
updateAlert: {
|
||||||
|
color: '#1d74f5'
|
||||||
|
},
|
||||||
status: {
|
status: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
bottom: -3,
|
bottom: -3,
|
||||||
|
@ -173,7 +176,7 @@ export default class RoomItem extends React.PureComponent {
|
||||||
|
|
||||||
get lastMessage() {
|
get lastMessage() {
|
||||||
const {
|
const {
|
||||||
lastMessage, alert, type
|
lastMessage, type
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!this.props.StoreLastMessage) {
|
if (!this.props.StoreLastMessage) {
|
||||||
|
@ -183,7 +186,6 @@ export default class RoomItem extends React.PureComponent {
|
||||||
return 'No Message';
|
return 'No Message';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let prefix = '';
|
let prefix = '';
|
||||||
|
|
||||||
if (lastMessage.u.username === this.props.user.username) {
|
if (lastMessage.u.username === this.props.user.username) {
|
||||||
|
@ -193,13 +195,7 @@ export default class RoomItem extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg = `${ prefix }${ lastMessage.msg.replace(/[\n\t\r]/igm, '') }`;
|
const msg = `${ prefix }${ lastMessage.msg.replace(/[\n\t\r]/igm, '') }`;
|
||||||
|
|
||||||
const maxChars = 35;
|
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 ? '...' : '' }`;
|
return `${ msg.slice(0, maxChars) }${ msg.replace(/:[a-z0-9]+:/gi, ':::').length > maxChars ? '...' : '' }`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +233,7 @@ export default class RoomItem extends React.PureComponent {
|
||||||
<View style={styles.roomNameView}>
|
<View style={styles.roomNameView}>
|
||||||
<View style={styles.firstRow}>
|
<View style={styles.firstRow}>
|
||||||
<Text style={[styles.roomName, alert && styles.alert]} 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, alert && styles.updateAlert]} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.row}>
|
<View style={styles.row}>
|
||||||
<Markdown
|
<Markdown
|
||||||
|
|
|
@ -14,6 +14,7 @@ import customEmojis from './customEmojis';
|
||||||
import activeUsers from './activeUsers';
|
import activeUsers from './activeUsers';
|
||||||
import starredMessages from './starredMessages';
|
import starredMessages from './starredMessages';
|
||||||
import pinnedMessages from './pinnedMessages';
|
import pinnedMessages from './pinnedMessages';
|
||||||
|
import mentionedMessages from './mentionedMessages';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
settings,
|
settings,
|
||||||
|
@ -30,5 +31,6 @@ export default combineReducers({
|
||||||
customEmojis,
|
customEmojis,
|
||||||
activeUsers,
|
activeUsers,
|
||||||
starredMessages,
|
starredMessages,
|
||||||
pinnedMessages
|
pinnedMessages,
|
||||||
|
mentionedMessages
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { MENTIONED_MESSAGES } from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
messages: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function server(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case MENTIONED_MESSAGES.MESSAGES_RECEIVED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
messages: [...state.messages, ...action.messages]
|
||||||
|
};
|
||||||
|
case MENTIONED_MESSAGES.CLOSE:
|
||||||
|
return initialState;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,21 @@
|
||||||
import { PINNED_MESSAGES } from '../actions/actionsTypes';
|
import { PINNED_MESSAGES } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
messages: []
|
messages: [],
|
||||||
|
isOpen: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function server(state = initialState, action) {
|
export default function server(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case PINNED_MESSAGES.MESSAGE_RECEIVED:
|
case PINNED_MESSAGES.OPEN:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
messages: [...state.messages, action.message]
|
isOpen: true
|
||||||
|
};
|
||||||
|
case PINNED_MESSAGES.MESSAGES_RECEIVED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
messages: [...state.messages, ...action.messages]
|
||||||
};
|
};
|
||||||
case PINNED_MESSAGES.MESSAGE_UNPINNED:
|
case PINNED_MESSAGES.MESSAGE_UNPINNED:
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
import { STARRED_MESSAGES } from '../actions/actionsTypes';
|
import { STARRED_MESSAGES } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
messages: []
|
messages: [],
|
||||||
|
isOpen: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function server(state = initialState, action) {
|
export default function server(state = initialState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case STARRED_MESSAGES.MESSAGE_RECEIVED:
|
case STARRED_MESSAGES.OPEN:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
messages: [...state.messages, action.message]
|
isOpen: true
|
||||||
|
};
|
||||||
|
case STARRED_MESSAGES.MESSAGES_RECEIVED:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
messages: [...state.messages, ...action.messages]
|
||||||
};
|
};
|
||||||
case STARRED_MESSAGES.MESSAGE_UNSTARRED:
|
case STARRED_MESSAGES.MESSAGE_UNSTARRED:
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import state from './state';
|
||||||
import activeUsers from './activeUsers';
|
import activeUsers from './activeUsers';
|
||||||
import starredMessages from './starredMessages';
|
import starredMessages from './starredMessages';
|
||||||
import pinnedMessages from './pinnedMessages';
|
import pinnedMessages from './pinnedMessages';
|
||||||
|
import mentionedMessages from './mentionedMessages';
|
||||||
|
|
||||||
const root = function* root() {
|
const root = function* root() {
|
||||||
yield all([
|
yield all([
|
||||||
|
@ -25,7 +26,8 @@ const root = function* root() {
|
||||||
state(),
|
state(),
|
||||||
activeUsers(),
|
activeUsers(),
|
||||||
starredMessages(),
|
starredMessages(),
|
||||||
pinnedMessages()
|
pinnedMessages(),
|
||||||
|
mentionedMessages()
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { take, takeLatest } from 'redux-saga/effects';
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
|
const watchMentionedMessagesRoom = function* watchMentionedMessagesRoom({ rid }) {
|
||||||
|
const sub = yield RocketChat.subscribe('mentionedMessages', rid, 50);
|
||||||
|
yield take(types.MENTIONED_MESSAGES.CLOSE);
|
||||||
|
sub.unsubscribe().catch(e => alert(e));
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = function* root() {
|
||||||
|
yield takeLatest(types.MENTIONED_MESSAGES.OPEN, watchMentionedMessagesRoom);
|
||||||
|
};
|
||||||
|
export default root;
|
|
@ -0,0 +1,71 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { FlatList, Text, View } from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { openMentionedMessages, closeMentionedMessages } from '../../actions/mentionedMessages';
|
||||||
|
import styles from './styles';
|
||||||
|
import Message from '../../containers/message';
|
||||||
|
|
||||||
|
@connect(
|
||||||
|
state => ({
|
||||||
|
messages: state.mentionedMessages.messages,
|
||||||
|
user: state.login.user,
|
||||||
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
||||||
|
}),
|
||||||
|
dispatch => ({
|
||||||
|
openMentionedMessages: rid => dispatch(openMentionedMessages(rid)),
|
||||||
|
closeMentionedMessages: () => dispatch(closeMentionedMessages())
|
||||||
|
})
|
||||||
|
)
|
||||||
|
export default class MentionedMessagesView extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object,
|
||||||
|
messages: PropTypes.array,
|
||||||
|
user: PropTypes.object,
|
||||||
|
baseUrl: PropTypes.string,
|
||||||
|
openMentionedMessages: PropTypes.func,
|
||||||
|
closeMentionedMessages: PropTypes.func
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.openMentionedMessages(this.props.navigation.state.params.rid);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.closeMentionedMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEmpty = () => (
|
||||||
|
<View style={styles.listEmptyContainer}>
|
||||||
|
<Text>No mentioned messages</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
|
||||||
|
renderItem = ({ item }) => (
|
||||||
|
<Message
|
||||||
|
item={item}
|
||||||
|
style={styles.message}
|
||||||
|
reactions={item.reactions}
|
||||||
|
user={this.props.user}
|
||||||
|
baseUrl={this.props.baseUrl}
|
||||||
|
Message_TimeFormat='MMMM Do YYYY, h:mm:ss a'
|
||||||
|
onLongPress={() => {}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.props.messages.length === 0) {
|
||||||
|
return this.renderEmpty();
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
key='mentioned-messages-view-list'
|
||||||
|
data={this.props.messages}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
style={styles.list}
|
||||||
|
keyExtractor={item => item._id}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
list: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#ffffff'
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
transform: [{ scaleY: 1 }]
|
||||||
|
},
|
||||||
|
listEmptyContainer: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: '#ffffff'
|
||||||
|
}
|
||||||
|
});
|
|
@ -43,7 +43,7 @@ export default class PinnedMessagesView extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentDidMount() {
|
||||||
this.props.openPinnedMessages(this.props.navigation.state.params.rid);
|
this.props.openPinnedMessages(this.props.navigation.state.params.rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { View, SectionList, Text, StyleSheet } from 'react-native';
|
import { View, SectionList, Text } from 'react-native';
|
||||||
import Icon from 'react-native-vector-icons/Ionicons';
|
import Icon from 'react-native-vector-icons/Ionicons';
|
||||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -9,6 +9,7 @@ import styles from './styles';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import database from '../../lib/realm';
|
import database from '../../lib/realm';
|
||||||
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
||||||
|
@ -29,25 +30,19 @@ export default class RoomActionsView extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentDidMount() {
|
||||||
this.updateRoom();
|
this.updateRoom();
|
||||||
this.updateSections();
|
this.updateSections();
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.rooms.addListener(this.updateRoom);
|
this.rooms.addListener(this.updateRoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRoom = () => {
|
updateRoom = () => {
|
||||||
const [room] = this.rooms;
|
const [room] = this.rooms;
|
||||||
this.setState({ room });
|
this.setState({ room });
|
||||||
this.props.navigation.setParams({
|
|
||||||
f: room.f
|
|
||||||
});
|
|
||||||
this.updateSections();
|
this.updateSections();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSections = () => {
|
updateSections = async() => {
|
||||||
const { rid, t } = this.state.room;
|
const { rid, t } = this.state.room;
|
||||||
const sections = [{
|
const sections = [{
|
||||||
data: [{ icon: 'ios-star', name: 'USER' }],
|
data: [{ icon: 'ios-star', name: 'USER' }],
|
||||||
|
@ -61,7 +56,12 @@ export default class RoomActionsView extends React.PureComponent {
|
||||||
}, {
|
}, {
|
||||||
data: [
|
data: [
|
||||||
{ icon: 'ios-attach', name: 'Files' },
|
{ icon: 'ios-attach', name: 'Files' },
|
||||||
{ icon: 'ios-at-outline', name: 'Mentions' },
|
{
|
||||||
|
icon: 'ios-at-outline',
|
||||||
|
name: 'Mentions',
|
||||||
|
route: 'MentionedMessages',
|
||||||
|
params: { rid }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: 'ios-star-outline',
|
icon: 'ios-star-outline',
|
||||||
name: 'Starred',
|
name: 'Starred',
|
||||||
|
@ -90,7 +90,16 @@ export default class RoomActionsView extends React.PureComponent {
|
||||||
renderItem: this.renderItem
|
renderItem: this.renderItem
|
||||||
});
|
});
|
||||||
} else if (t === 'c' || t === 'p') {
|
} else if (t === 'c' || t === 'p') {
|
||||||
sections[2].data.unshift({ icon: 'ios-people', name: 'Members', description: '42 members' });
|
const membersResult = await RocketChat.getRoomMembers(rid, false);
|
||||||
|
const members = membersResult.records;
|
||||||
|
|
||||||
|
sections[2].data.unshift({
|
||||||
|
icon: 'ios-people',
|
||||||
|
name: 'Members',
|
||||||
|
description: (members.length === 1 ? `${ members.length } member` : `${ members.length } members`),
|
||||||
|
route: 'RoomMembers',
|
||||||
|
params: { rid, members }
|
||||||
|
});
|
||||||
sections.push({
|
sections.push({
|
||||||
data: [
|
data: [
|
||||||
{ icon: 'ios-volume-off', name: 'Mute channel' },
|
{ icon: 'ios-volume-off', name: 'Mute channel' },
|
||||||
|
@ -102,21 +111,28 @@ export default class RoomActionsView extends React.PureComponent {
|
||||||
this.setState({ sections });
|
this.setState({ sections });
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRoomInfo = ({ item }) => this.renderTouchableItem([
|
renderRoomInfo = ({ item }) => {
|
||||||
<Avatar
|
const {
|
||||||
key='avatar'
|
fname, name, t, topic
|
||||||
text={this.state.room.name}
|
} = this.state.room;
|
||||||
size={50}
|
return (
|
||||||
style={StyleSheet.flatten(styles.avatar)}
|
this.renderTouchableItem([
|
||||||
baseUrl={this.props.baseUrl}
|
<Avatar
|
||||||
type={this.state.room.t}
|
key='avatar'
|
||||||
/>,
|
text={name}
|
||||||
<View key='name' style={styles.roomTitleContainer}>
|
size={50}
|
||||||
<Text style={styles.roomTitle}>{this.state.room.fname}</Text>
|
style={styles.avatar}
|
||||||
<Text style={styles.roomDescription}>@{this.state.room.name}</Text>
|
baseUrl={this.props.baseUrl}
|
||||||
</View>,
|
type={t}
|
||||||
<Icon key='icon' name='ios-arrow-forward' size={20} style={styles.sectionItemIcon} color='#cbced1' />
|
/>,
|
||||||
], item)
|
<View key='name' style={styles.roomTitleContainer}>
|
||||||
|
<Text style={styles.roomTitle}>{t === 'd' ? fname : name}</Text>
|
||||||
|
<Text style={styles.roomDescription} ellipsizeMode='tail' numberOfLines={1}>{t === 'd' ? `@${ name }` : topic}</Text>
|
||||||
|
</View>,
|
||||||
|
<Icon key='icon' name='ios-arrow-forward' size={20} style={styles.sectionItemIcon} color='#cbced1' />
|
||||||
|
], item)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderTouchableItem = (subview, item) => (
|
renderTouchableItem = (subview, item) => (
|
||||||
<Touch
|
<Touch
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { FlatList, Text, View, TextInput } from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
import Avatar from '../../containers/Avatar';
|
||||||
|
import Status from '../../containers/status';
|
||||||
|
import Touch from '../../utils/touch';
|
||||||
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import { goRoom } from '../../containers/routes/NavigationService';
|
||||||
|
import database from '../../lib/realm';
|
||||||
|
|
||||||
|
@connect(state => ({
|
||||||
|
user: state.login.user,
|
||||||
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
||||||
|
}))
|
||||||
|
export default class MentionedMessagesView extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object
|
||||||
|
}
|
||||||
|
|
||||||
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const params = navigation.state.params || {};
|
||||||
|
const label = params.allUsers ? 'All' : 'Online';
|
||||||
|
if (params.allUsers === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
headerRight: (
|
||||||
|
<Touch
|
||||||
|
onPress={params.onPressToogleStatus}
|
||||||
|
underlayColor='#ffffff'
|
||||||
|
activeOpacity={0.5}
|
||||||
|
accessibilityLabel={label}
|
||||||
|
accessibilityTraits='button'
|
||||||
|
style={styles.headerButtonTouchable}
|
||||||
|
>
|
||||||
|
<View style={styles.headerButton}>
|
||||||
|
<Text style={styles.headerButtonText}>{label}</Text>
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
const { rid, members } = props.navigation.state.params;
|
||||||
|
this.state = {
|
||||||
|
allUsers: false,
|
||||||
|
filtering: false,
|
||||||
|
rid,
|
||||||
|
members,
|
||||||
|
membersFiltered: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.props.navigation.setParams({
|
||||||
|
onPressToogleStatus: this.onPressToogleStatus,
|
||||||
|
allUsers: this.state.allUsers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchChangeText = (text) => {
|
||||||
|
let membersFiltered = [];
|
||||||
|
if (text) {
|
||||||
|
membersFiltered = this.state.members.filter(m => m.username.toLowerCase().match(text.toLowerCase()));
|
||||||
|
}
|
||||||
|
this.setState({ filtering: !!text, membersFiltered });
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressToogleStatus = async() => {
|
||||||
|
const allUsers = !this.state.allUsers;
|
||||||
|
this.props.navigation.setParams({ allUsers });
|
||||||
|
const membersResult = await RocketChat.getRoomMembers(this.state.rid, allUsers);
|
||||||
|
const members = membersResult.records;
|
||||||
|
this.setState({ allUsers, members });
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressItem = async(item) => {
|
||||||
|
const subscriptions = database.objects('subscriptions').filtered('name = $0', item.username);
|
||||||
|
if (subscriptions.length) {
|
||||||
|
goRoom({ rid: subscriptions[0].rid, name: subscriptions[0].name });
|
||||||
|
} else {
|
||||||
|
const room = await RocketChat.createDirectMessage(item.username);
|
||||||
|
goRoom({ room: room.rid, name: item.username });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSearchBar = () => (
|
||||||
|
<View style={styles.searchBoxView}>
|
||||||
|
<TextInput
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
|
style={styles.searchBox}
|
||||||
|
onChangeText={text => this.onSearchChangeText(text)}
|
||||||
|
returnKeyType='search'
|
||||||
|
placeholder='Search'
|
||||||
|
clearButtonMode='while-editing'
|
||||||
|
blurOnSubmit
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
|
||||||
|
renderSeparator = () => <View style={styles.separator} />;
|
||||||
|
|
||||||
|
renderItem = ({ item }) => (
|
||||||
|
<Touch
|
||||||
|
onPress={() => this.onPressItem(item)}
|
||||||
|
underlayColor='#ffffff'
|
||||||
|
activeOpacity={0.5}
|
||||||
|
accessibilityLabel={`Start a conversation with ${ item.username }`}
|
||||||
|
accessibilityTraits='button'
|
||||||
|
>
|
||||||
|
<View style={styles.item}>
|
||||||
|
<Avatar text={item.username} size={30} type='d' style={styles.avatar}>{<Status style={styles.status} id={item._id} />}</Avatar>
|
||||||
|
<Text style={styles.username}>{item.username}</Text>
|
||||||
|
</View>
|
||||||
|
</Touch>
|
||||||
|
)
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { filtering, members, membersFiltered } = this.state;
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
key='room-members-view-list'
|
||||||
|
data={filtering ? membersFiltered : members}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
style={styles.list}
|
||||||
|
keyExtractor={item => item._id}
|
||||||
|
ItemSeparatorComponent={this.renderSeparator}
|
||||||
|
ListHeaderComponent={this.renderSearchBar}
|
||||||
|
{...scrollPersistTaps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
list: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#ffffff'
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
paddingVertical: 8,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
marginRight: 16
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: -3,
|
||||||
|
right: -3,
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderRadius: 12,
|
||||||
|
width: 12,
|
||||||
|
height: 12
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
height: StyleSheet.hairlineWidth,
|
||||||
|
backgroundColor: '#ddd'
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#444'
|
||||||
|
},
|
||||||
|
headerButtonTouchable: {
|
||||||
|
borderRadius: 4
|
||||||
|
},
|
||||||
|
headerButton: {
|
||||||
|
padding: 6,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
headerButtonText: {
|
||||||
|
color: '#292E35'
|
||||||
|
},
|
||||||
|
searchBoxView: {
|
||||||
|
backgroundColor: '#eee'
|
||||||
|
},
|
||||||
|
searchBox: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
margin: 5,
|
||||||
|
borderRadius: 5,
|
||||||
|
padding: 5,
|
||||||
|
paddingLeft: 10,
|
||||||
|
color: '#aaa'
|
||||||
|
}
|
||||||
|
});
|
|
@ -27,7 +27,7 @@ export class DataSource extends OldList.DataSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ds = new DataSource({ rowHasChanged: (r1, r2) => r1._id !== r2._id });
|
const ds = new DataSource({ rowHasChanged: (r1, r2) => r1._id !== r2._id || r1._updatedAt.toISOString() !== r2._updatedAt.toISOString() });
|
||||||
|
|
||||||
export class List extends React.Component {
|
export class List extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -78,7 +78,7 @@ export default class RoomView extends React.Component {
|
||||||
this.onReactionPress = this.onReactionPress.bind(this);
|
this.onReactionPress = this.onReactionPress.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentWillMount() {
|
async componentDidMount() {
|
||||||
this.props.navigation.setParams({
|
this.props.navigation.setParams({
|
||||||
title: this.name
|
title: this.name
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default class StarredMessagesView extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentDidMount() {
|
||||||
this.props.openStarredMessages(this.props.navigation.state.params.rid);
|
this.props.openStarredMessages(this.props.navigation.state.params.rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue