Merge 2f3b58424c
into e09ca3d6a7
This commit is contained in:
commit
931ca41d04
|
@ -1,3 +1,5 @@
|
|||
# Clear CI cache
|
||||
|
||||
defaults: &defaults
|
||||
working_directory: ~/repo
|
||||
|
||||
|
|
|
@ -28,7 +28,26 @@ export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [
|
|||
]);
|
||||
export const ROOMS = createRequestTypes('ROOMS');
|
||||
export const APP = createRequestTypes('APP', ['READY', 'INIT']);
|
||||
export const MESSAGES = createRequestTypes('MESSAGES');
|
||||
export const MESSAGES = createRequestTypes('MESSAGES', [
|
||||
...defaultTypes,
|
||||
'DELETE_REQUEST',
|
||||
'DELETE_SUCCESS',
|
||||
'DELETE_FAILURE',
|
||||
'EDIT_INIT',
|
||||
'EDIT_REQUEST',
|
||||
'EDIT_SUCCESS',
|
||||
'EDIT_FAILURE',
|
||||
'STAR_REQUEST',
|
||||
'STAR_SUCCESS',
|
||||
'STAR_FAILURE',
|
||||
'PERMALINK_REQUEST',
|
||||
'PERMALINK_SUCCESS',
|
||||
'PERMALINK_FAILURE',
|
||||
'TOGGLE_PIN_REQUEST',
|
||||
'TOGGLE_PIN_SUCCESS',
|
||||
'TOGGLE_PIN_FAILURE',
|
||||
'SET_INPUT'
|
||||
]);
|
||||
export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [
|
||||
...defaultTypes,
|
||||
'REQUEST_USERS',
|
||||
|
|
|
@ -19,3 +19,116 @@ export function messagesFailure(err) {
|
|||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteRequest(message) {
|
||||
return {
|
||||
type: types.MESSAGES.DELETE_REQUEST,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteSuccess() {
|
||||
return {
|
||||
type: types.MESSAGES.DELETE_SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteFailure() {
|
||||
return {
|
||||
type: types.MESSAGES.DELETE_FAILURE
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export function editInit(message) {
|
||||
return {
|
||||
type: types.MESSAGES.EDIT_INIT,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function editRequest(message) {
|
||||
return {
|
||||
type: types.MESSAGES.EDIT_REQUEST,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function editSuccess() {
|
||||
return {
|
||||
type: types.MESSAGES.EDIT_SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function editFailure() {
|
||||
return {
|
||||
type: types.MESSAGES.EDIT_FAILURE
|
||||
};
|
||||
}
|
||||
|
||||
export function starRequest(message) {
|
||||
return {
|
||||
type: types.MESSAGES.STAR_REQUEST,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function starSuccess() {
|
||||
return {
|
||||
type: types.MESSAGES.STAR_SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function starFailure() {
|
||||
return {
|
||||
type: types.MESSAGES.STAR_FAILURE
|
||||
};
|
||||
}
|
||||
|
||||
export function permalinkRequest(message) {
|
||||
return {
|
||||
type: types.MESSAGES.PERMALINK_REQUEST,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function permalinkSuccess(permalink) {
|
||||
return {
|
||||
type: types.MESSAGES.PERMALINK_SUCCESS,
|
||||
permalink
|
||||
};
|
||||
}
|
||||
|
||||
export function permalinkFailure(err) {
|
||||
return {
|
||||
type: types.MESSAGES.PERMALINK_FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function togglePinRequest(message) {
|
||||
return {
|
||||
type: types.MESSAGES.TOGGLE_PIN_REQUEST,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
export function togglePinSuccess() {
|
||||
return {
|
||||
type: types.MESSAGES.TOGGLE_PIN_SUCCESS
|
||||
};
|
||||
}
|
||||
|
||||
export function togglePinFailure(err) {
|
||||
return {
|
||||
type: types.MESSAGES.TOGGLE_PIN_FAILURE,
|
||||
err
|
||||
};
|
||||
}
|
||||
|
||||
export function setInput(message) {
|
||||
return {
|
||||
type: types.MESSAGES.SET_INPUT,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { emojify } from 'react-emojione';
|
||||
import Markdown from 'react-native-easy-markdown';
|
||||
|
||||
import Card from './message/Card';
|
||||
import Avatar from './Avatar';
|
||||
import User from './message/User';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
flexShrink: 1
|
||||
},
|
||||
message: {
|
||||
padding: 12,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 6,
|
||||
flexDirection: 'row',
|
||||
transform: [{ scaleY: -1 }]
|
||||
}
|
||||
});
|
||||
|
||||
export default class Message extends React.PureComponent {
|
||||
static propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
baseUrl: PropTypes.string.isRequired,
|
||||
Message_TimeFormat: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
attachments() {
|
||||
return this.props.item.attachments.length ? (
|
||||
<Card
|
||||
data={this.props.item.attachments[0]}
|
||||
/>
|
||||
) : null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
|
||||
const extraStyle = {};
|
||||
if (item.temp) {
|
||||
extraStyle.opacity = 0.3;
|
||||
}
|
||||
|
||||
const msg = emojify(item.msg, { output: 'unicode' });
|
||||
const username = item.alias || item.u.username;
|
||||
|
||||
return (
|
||||
<View style={[styles.message, extraStyle]}>
|
||||
<Avatar
|
||||
style={{ marginRight: 10 }}
|
||||
text={item.avatar ? '' : username}
|
||||
size={40}
|
||||
baseUrl={this.props.baseUrl}
|
||||
avatar={item.avatar}
|
||||
/>
|
||||
<View style={[styles.content]}>
|
||||
<User
|
||||
onPress={this._onPress}
|
||||
item={item}
|
||||
Message_TimeFormat={this.props.Message_TimeFormat}
|
||||
/>
|
||||
{this.attachments()}
|
||||
<Markdown>
|
||||
{msg}
|
||||
</Markdown>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
|
|||
import { View, TextInput, StyleSheet, SafeAreaView } from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import ImagePicker from 'react-native-image-picker';
|
||||
import { connect } from 'react-redux';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import { editRequest } from '../actions/messages';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
textBox: {
|
||||
|
@ -19,7 +21,6 @@ const styles = StyleSheet.create({
|
|||
textBoxInput: {
|
||||
height: 40,
|
||||
alignSelf: 'stretch',
|
||||
backgroundColor: '#fff',
|
||||
flexGrow: 1
|
||||
},
|
||||
fileButton: {
|
||||
|
@ -29,24 +30,55 @@ const styles = StyleSheet.create({
|
|||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
fontSize: 20
|
||||
},
|
||||
editing: {
|
||||
backgroundColor: '#fff5df'
|
||||
}
|
||||
});
|
||||
|
||||
export default class MessageBox extends React.PureComponent {
|
||||
@connect(state => ({
|
||||
message: state.messages.message,
|
||||
editing: state.messages.editing
|
||||
}), dispatch => ({
|
||||
editRequest: message => dispatch(editRequest(message))
|
||||
}))
|
||||
export default class MessageBox extends React.Component {
|
||||
static propTypes = {
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
rid: PropTypes.string.isRequired
|
||||
editRequest: PropTypes.func.isRequired,
|
||||
rid: PropTypes.string.isRequired,
|
||||
message: PropTypes.object,
|
||||
editing: PropTypes.bool
|
||||
}
|
||||
|
||||
submit(message) {
|
||||
const text = message;
|
||||
if (text.trim() === '') {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { message: '' };
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.message !== nextProps.message) {
|
||||
this.setState({ message: nextProps.message.msg });
|
||||
this.component.focus();
|
||||
}
|
||||
}
|
||||
|
||||
submit() {
|
||||
const { message } = this.state;
|
||||
const { editing } = this.props;
|
||||
if (message.trim() === '') {
|
||||
return;
|
||||
}
|
||||
if (this.component) {
|
||||
this.component.setNativeProps({ text: '' });
|
||||
|
||||
// if is editing a message
|
||||
if (editing) {
|
||||
const { _id, rid } = this.props.message;
|
||||
this.props.editRequest({ _id, msg: message, rid });
|
||||
} else {
|
||||
// if is submiting a new message
|
||||
this.props.onSubmit(message);
|
||||
}
|
||||
this.props.onSubmit(text);
|
||||
this.setState({ message: '' });
|
||||
}
|
||||
|
||||
addFile = () => {
|
||||
|
@ -78,18 +110,20 @@ export default class MessageBox extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.textBox}>
|
||||
<View style={[styles.textBox, (this.props.editing ? styles.editing : null)]}>
|
||||
<SafeAreaView style={styles.safeAreaView}>
|
||||
<Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} />
|
||||
<TextInput
|
||||
ref={component => this.component = component}
|
||||
style={styles.textBoxInput}
|
||||
returnKeyType='send'
|
||||
onSubmitEditing={event => this.submit(event.nativeEvent.text)}
|
||||
onSubmitEditing={() => this.submit()}
|
||||
blurOnSubmit={false}
|
||||
placeholder='New message'
|
||||
underlineColorAndroid='transparent'
|
||||
defaultValue=''
|
||||
value={this.state.message}
|
||||
onChangeText={message => this.setState({ message })}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
|
|
|
@ -55,7 +55,7 @@ export default class Cards extends React.PureComponent {
|
|||
</Card>
|
||||
</TouchableOpacity>
|
||||
<PhotoModal
|
||||
title={this.props.data.title}
|
||||
title={this.props.data.title || 'test'}
|
||||
image={this.state.img}
|
||||
isVisible={this.state.modalVisible}
|
||||
onClose={() => this.setState({ modalVisible: false })}
|
||||
|
|
|
@ -2,6 +2,8 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import moment from 'moment';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import Avatar from '../Avatar';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
username: {
|
||||
|
@ -21,6 +23,11 @@ const styles = StyleSheet.create({
|
|||
fontSize: 10,
|
||||
color: '#888',
|
||||
paddingLeft: 5
|
||||
},
|
||||
edited: {
|
||||
marginLeft: 5,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -28,7 +35,26 @@ export default class Message extends React.PureComponent {
|
|||
static propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
Message_TimeFormat: PropTypes.string.isRequired,
|
||||
onPress: PropTypes.func
|
||||
onPress: PropTypes.func,
|
||||
baseUrl: PropTypes.string
|
||||
}
|
||||
|
||||
renderEdited(item) {
|
||||
if (!item.editedBy) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View style={styles.edited}>
|
||||
<Icon name='pencil-square-o' color='#888' size={10} />
|
||||
<Avatar
|
||||
style={{ marginLeft: 5 }}
|
||||
text={item.editedBy.username}
|
||||
size={20}
|
||||
baseUrl={this.props.baseUrl}
|
||||
avatar={item.avatar}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -48,7 +74,9 @@ export default class Message extends React.PureComponent {
|
|||
<Text onPress={this.props.onPress} style={styles.username}>
|
||||
{username}
|
||||
</Text>
|
||||
{aliasUsername}<Text style={styles.time}>{time}</Text>
|
||||
{aliasUsername}
|
||||
<Text style={styles.time}>{time}</Text>
|
||||
{this.renderEdited(item)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, StyleSheet, TouchableOpacity, Text, Alert, Clipboard } from 'react-native';
|
||||
import { emojify } from 'react-emojione';
|
||||
import Markdown from 'react-native-easy-markdown'; // eslint-disable-line
|
||||
// import ActionSheet from 'react-native-actionsheet';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import Card from './Card';
|
||||
import User from './User';
|
||||
import Avatar from '../Avatar';
|
||||
import {
|
||||
deleteRequest,
|
||||
editInit,
|
||||
starRequest,
|
||||
permalinkRequest,
|
||||
togglePinRequest,
|
||||
setInput
|
||||
} from '../../actions/messages';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
|
||||
// const title = 'Message actions';
|
||||
// const options = ['Cancel', 'Reply', 'Edit', 'Permalink', 'Copy', 'Quote', 'Star Message', 'Pin Message', 'Delete'];
|
||||
// const CANCEL_INDEX = 0;
|
||||
// const DESTRUCTIVE_INDEX = 8;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
flexShrink: 1
|
||||
},
|
||||
message: {
|
||||
padding: 12,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 6,
|
||||
flexDirection: 'row',
|
||||
transform: [{ scaleY: -1 }]
|
||||
},
|
||||
textInfo: {
|
||||
fontStyle: 'italic',
|
||||
color: '#a0a0a0'
|
||||
},
|
||||
editing: {
|
||||
backgroundColor: '#fff5df'
|
||||
}
|
||||
});
|
||||
|
||||
@connect(state => ({
|
||||
message: state.messages.message,
|
||||
permalink: state.messages.permalink,
|
||||
user: state.login.user
|
||||
}), dispatch => ({
|
||||
deleteRequest: message => dispatch(deleteRequest(message)),
|
||||
editInit: message => dispatch(editInit(message)),
|
||||
starRequest: message => dispatch(starRequest(message)),
|
||||
permalinkRequest: message => dispatch(permalinkRequest(message)),
|
||||
togglePinRequest: message => dispatch(togglePinRequest(message)),
|
||||
setInput: message => dispatch(setInput(message))
|
||||
}))
|
||||
export default class Message extends React.Component {
|
||||
static propTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
baseUrl: PropTypes.string.isRequired,
|
||||
Message_TimeFormat: PropTypes.string.isRequired,
|
||||
deleteRequest: PropTypes.func.isRequired,
|
||||
editInit: PropTypes.func.isRequired,
|
||||
starRequest: PropTypes.func.isRequired,
|
||||
permalinkRequest: PropTypes.func.isRequired,
|
||||
togglePinRequest: PropTypes.func.isRequired,
|
||||
setInput: PropTypes.func.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
message: PropTypes.object,
|
||||
permalink: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
copyPermalink: false,
|
||||
reply: false,
|
||||
quote: false
|
||||
};
|
||||
this.handleActionPress = this.handleActionPress.bind(this);
|
||||
this.showActions = this.showActions.bind(this);
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
if (this.props.permalink !== nextProps.permalink) {
|
||||
// copy permalink
|
||||
if (this.state.copyPermalink) {
|
||||
this.setState({ copyPermalink: false });
|
||||
await Clipboard.setString(nextProps.permalink);
|
||||
Alert.alert('Permalink copied to clipboard!');
|
||||
|
||||
// quote
|
||||
} else if (this.state.quote) {
|
||||
this.setState({ quote: false });
|
||||
const msg = `[ ](${ nextProps.permalink }) `;
|
||||
this.props.setInput({ msg });
|
||||
|
||||
// reply
|
||||
} else if (this.state.reply) {
|
||||
this.setState({ reply: false });
|
||||
let msg = `[ ](${ nextProps.permalink }) `;
|
||||
const room = await RocketChat.getRoom(this.props.item.rid);
|
||||
|
||||
// if original message wasn't sent by current user and neither from a direct room
|
||||
if (this.props.user.username !== this.props.item.u.username && room.t !== 'd') {
|
||||
msg += `@${ this.props.item.u.username } `;
|
||||
}
|
||||
this.props.setInput({ msg });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isDeleted() {
|
||||
return !this.props.item.msg;
|
||||
}
|
||||
|
||||
attachments() {
|
||||
return this.props.item.attachments.length ? (
|
||||
<Card
|
||||
data={this.props.item.attachments[0]}
|
||||
/>
|
||||
) : null;
|
||||
}
|
||||
|
||||
showActions = () => {
|
||||
// this.ActionSheet.show();
|
||||
console.log('temp');
|
||||
}
|
||||
|
||||
handleDelete() {
|
||||
Alert.alert(
|
||||
'Are you sure?',
|
||||
'You will not be able to recover this message!',
|
||||
[
|
||||
{
|
||||
text: 'Cancel',
|
||||
style: 'cancel'
|
||||
},
|
||||
{
|
||||
text: 'Yes, delete it!',
|
||||
style: 'destructive',
|
||||
onPress: () => this.props.deleteRequest(this.props.item)
|
||||
}
|
||||
],
|
||||
{ cancelable: false }
|
||||
);
|
||||
}
|
||||
|
||||
handleEdit() {
|
||||
const { _id, msg, rid } = this.props.item;
|
||||
this.props.editInit({ _id, msg, rid });
|
||||
}
|
||||
|
||||
handleCopy = async() => {
|
||||
await Clipboard.setString(this.props.item.msg);
|
||||
Alert.alert('Copied to clipboard!');
|
||||
}
|
||||
|
||||
handleStar() {
|
||||
this.props.starRequest(this.props.item);
|
||||
}
|
||||
|
||||
handlePermalink() {
|
||||
this.setState({ copyPermalink: true });
|
||||
this.props.permalinkRequest(this.props.item);
|
||||
}
|
||||
|
||||
handleTogglePin() {
|
||||
this.props.togglePinRequest(this.props.item);
|
||||
}
|
||||
|
||||
handleReply() {
|
||||
this.setState({ reply: true });
|
||||
this.props.permalinkRequest(this.props.item);
|
||||
}
|
||||
|
||||
handleQuote() {
|
||||
this.setState({ quote: true });
|
||||
this.props.permalinkRequest(this.props.item);
|
||||
}
|
||||
|
||||
handleActionPress = (actionIndex) => {
|
||||
// reply
|
||||
if (actionIndex === 1) {
|
||||
this.handleReply();
|
||||
// edit
|
||||
} else if (actionIndex === 2) {
|
||||
this.handleEdit();
|
||||
// permalink
|
||||
} else if (actionIndex === 3) {
|
||||
this.handlePermalink();
|
||||
// copy
|
||||
} else if (actionIndex === 4) {
|
||||
this.handleCopy();
|
||||
// quote
|
||||
} else if (actionIndex === 5) {
|
||||
this.handleQuote();
|
||||
// star
|
||||
} else if (actionIndex === 6) {
|
||||
this.handleStar();
|
||||
// toggle pin
|
||||
} else if (actionIndex === 7) {
|
||||
this.handleTogglePin();
|
||||
// delete
|
||||
} else if (actionIndex === 8) {
|
||||
this.handleDelete();
|
||||
// reply
|
||||
} else {
|
||||
console.log(actionIndex, this.props.item);
|
||||
}
|
||||
}
|
||||
|
||||
renderMessageContent() {
|
||||
if (this.isDeleted()) {
|
||||
return <Text style={styles.textInfo}>Message removed</Text>;
|
||||
}
|
||||
|
||||
const msg = emojify(this.props.item.msg, { output: 'unicode' });
|
||||
return (
|
||||
<Markdown>
|
||||
{msg}
|
||||
</Markdown>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
|
||||
const extraStyle = {};
|
||||
if (item.temp) {
|
||||
extraStyle.opacity = 0.3;
|
||||
}
|
||||
|
||||
const username = item.alias || item.u.username;
|
||||
const isEditing = this.props.message._id === item._id;
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onLongPress={() => this.showActions()}
|
||||
disabled={this.isDeleted()}
|
||||
style={isEditing ? styles.editing : null}
|
||||
>
|
||||
<View style={[styles.message, extraStyle]}>
|
||||
<Avatar
|
||||
style={{ marginRight: 10 }}
|
||||
text={item.avatar ? '' : username}
|
||||
size={40}
|
||||
baseUrl={this.props.baseUrl}
|
||||
avatar={item.avatar}
|
||||
/>
|
||||
<View style={[styles.content]}>
|
||||
<User
|
||||
onPress={this._onPress}
|
||||
item={item}
|
||||
Message_TimeFormat={this.props.Message_TimeFormat}
|
||||
baseUrl={this.props.baseUrl}
|
||||
/>
|
||||
{this.attachments()}
|
||||
{this.renderMessageContent(item)}
|
||||
</View>
|
||||
{/* <ActionSheet
|
||||
ref={o => this.ActionSheet = o}
|
||||
title={title}
|
||||
options={options}
|
||||
cancelButtonIndex={CANCEL_INDEX}
|
||||
destructiveButtonIndex={DESTRUCTIVE_INDEX}
|
||||
onPress={this.handleActionPress}
|
||||
/> */}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -84,6 +84,14 @@ const attachment = {
|
|||
}
|
||||
};
|
||||
|
||||
const messagesEditedBySchema = {
|
||||
name: 'messagesEditedBy',
|
||||
properties: {
|
||||
_id: { type: 'string', optional: true },
|
||||
username: { type: 'string', optional: true }
|
||||
}
|
||||
};
|
||||
|
||||
const messagesSchema = {
|
||||
name: 'messages',
|
||||
primaryKey: '_id',
|
||||
|
@ -102,14 +110,26 @@ const messagesSchema = {
|
|||
avatar: { type: 'string', optional: true },
|
||||
attachments: { type: 'list', objectType: 'attachment' },
|
||||
_updatedAt: { type: 'date', optional: true },
|
||||
temp: { type: 'bool', optional: true }
|
||||
temp: { type: 'bool', optional: true },
|
||||
pinned: { type: 'bool', optional: true },
|
||||
starred: { type: 'bool', optional: true },
|
||||
editedBy: 'messagesEditedBy'
|
||||
}
|
||||
};
|
||||
//
|
||||
// Realm.clearTestState();
|
||||
// AsyncStorage.clear();
|
||||
const realm = new Realm({
|
||||
schema: [settingsSchema, serversSchema, subscriptionSchema, messagesSchema, usersSchema, roomsSchema, attachment]
|
||||
schema: [
|
||||
settingsSchema,
|
||||
serversSchema,
|
||||
subscriptionSchema,
|
||||
messagesSchema,
|
||||
usersSchema,
|
||||
roomsSchema,
|
||||
attachment,
|
||||
messagesEditedBySchema
|
||||
]
|
||||
});
|
||||
export default realm;
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ const RocketChat = {
|
|||
const message = ddbMessage.fields.args[0];
|
||||
message.temp = false;
|
||||
message._server = { id: reduxStore.getState().server.server };
|
||||
message.starred = !!message.starred;
|
||||
realm.create('messages', message, true);
|
||||
});
|
||||
}
|
||||
|
@ -285,6 +286,7 @@ const RocketChat = {
|
|||
message.temp = false;
|
||||
message._server = { id: reduxStore.getState().server.server };
|
||||
// write('messages', message);
|
||||
message.starred = !!message.starred;
|
||||
realm.create('messages', message, true);
|
||||
});
|
||||
});
|
||||
|
@ -469,6 +471,58 @@ const RocketChat = {
|
|||
Meteor.disconnect();
|
||||
AsyncStorage.removeItem(TOKEN_KEY);
|
||||
AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`);
|
||||
},
|
||||
deleteMessage(message) {
|
||||
return call('deleteMessage', { _id: message._id });
|
||||
},
|
||||
editMessage(message) {
|
||||
const { _id, msg, rid } = message;
|
||||
return call('updateMessage', { _id, msg, rid });
|
||||
},
|
||||
starMessage(message) {
|
||||
return call('starMessage', { _id: message._id, rid: message.rid, starred: !message.starred });
|
||||
},
|
||||
togglePinMessage(message) {
|
||||
if (message.pinned) {
|
||||
return call('unpinMessage', message);
|
||||
}
|
||||
return call('pinMessage', message);
|
||||
},
|
||||
getRoom(rid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const result = realm.objects('subscriptions').filtered('rid = $0', rid);
|
||||
|
||||
if (result.length === 0) {
|
||||
return reject(new Error('Room not found'));
|
||||
}
|
||||
return resolve(result[0]);
|
||||
});
|
||||
},
|
||||
async getPermalink(message) {
|
||||
return new Promise(async(resolve, reject) => {
|
||||
let room;
|
||||
try {
|
||||
room = await RocketChat.getRoom(message.rid);
|
||||
} catch (error) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
let roomType;
|
||||
switch (room.t) {
|
||||
case 'p':
|
||||
roomType = 'group';
|
||||
break;
|
||||
case 'c':
|
||||
roomType = 'channel';
|
||||
break;
|
||||
case 'd':
|
||||
roomType = 'direct';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return resolve(`${ room._server.id }/${ roomType }/${ room.name }?msg=${ message._id }`);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@ import * as types from '../actions/actionsTypes';
|
|||
|
||||
const initialState = {
|
||||
isFetching: false,
|
||||
failure: false
|
||||
failure: false,
|
||||
message: {},
|
||||
editing: false,
|
||||
permalink: ''
|
||||
};
|
||||
|
||||
export default function messages(state = initialState, action) {
|
||||
|
@ -24,8 +27,28 @@ export default function messages(state = initialState, action) {
|
|||
failure: true,
|
||||
errorMessage: action.err
|
||||
};
|
||||
// case types.LOGOUT:
|
||||
// return initialState;
|
||||
case types.MESSAGES.EDIT_INIT:
|
||||
return {
|
||||
...state,
|
||||
message: action.message,
|
||||
editing: true
|
||||
};
|
||||
case types.MESSAGES.EDIT_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
message: {},
|
||||
editing: false
|
||||
};
|
||||
case types.MESSAGES.PERMALINK_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
permalink: action.permalink
|
||||
};
|
||||
case types.MESSAGES.SET_INPUT:
|
||||
return {
|
||||
...state,
|
||||
message: action.message
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,27 @@
|
|||
import { takeLatest, select, take, put } from 'redux-saga/effects';
|
||||
import { takeLatest, select, take, put, call } from 'redux-saga/effects';
|
||||
import { MESSAGES, LOGIN } from '../actions/actionsTypes';
|
||||
import { messagesSuccess, messagesFailure } from '../actions/messages';
|
||||
import {
|
||||
messagesSuccess,
|
||||
messagesFailure,
|
||||
deleteSuccess,
|
||||
deleteFailure,
|
||||
editSuccess,
|
||||
editFailure,
|
||||
starSuccess,
|
||||
starFailure,
|
||||
permalinkSuccess,
|
||||
permalinkFailure,
|
||||
togglePinSuccess,
|
||||
togglePinFailure
|
||||
} from '../actions/messages';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
||||
const deleteMessage = message => RocketChat.deleteMessage(message);
|
||||
const editMessage = message => RocketChat.editMessage(message);
|
||||
const starMessage = message => RocketChat.starMessage(message);
|
||||
const getPermalink = message => RocketChat.getPermalink(message);
|
||||
const togglePinMessage = message => RocketChat.togglePinMessage(message);
|
||||
|
||||
const get = function* get({ rid }) {
|
||||
const auth = yield select(state => state.login.isAuthenticated);
|
||||
if (!auth) {
|
||||
|
@ -17,7 +36,58 @@ const get = function* get({ rid }) {
|
|||
yield put(messagesFailure(err.status));
|
||||
}
|
||||
};
|
||||
const getData = function* getData() {
|
||||
yield takeLatest(MESSAGES.REQUEST, get);
|
||||
|
||||
const handleDeleteRequest = function* handleDeleteRequest({ message }) {
|
||||
try {
|
||||
yield call(deleteMessage, message);
|
||||
yield put(deleteSuccess());
|
||||
} catch (error) {
|
||||
yield put(deleteFailure());
|
||||
}
|
||||
};
|
||||
export default getData;
|
||||
|
||||
const handleEditRequest = function* handleEditRequest({ message }) {
|
||||
try {
|
||||
yield call(editMessage, message);
|
||||
yield put(editSuccess());
|
||||
} catch (error) {
|
||||
yield put(editFailure());
|
||||
}
|
||||
};
|
||||
|
||||
const handleStarRequest = function* handleStarRequest({ message }) {
|
||||
try {
|
||||
yield call(starMessage, message);
|
||||
yield put(starSuccess());
|
||||
} catch (error) {
|
||||
yield put(starFailure());
|
||||
}
|
||||
};
|
||||
|
||||
const handlePermalinkRequest = function* handlePermalinkRequest({ message }) {
|
||||
try {
|
||||
const permalink = yield call(getPermalink, message);
|
||||
yield put(permalinkSuccess(permalink));
|
||||
} catch (error) {
|
||||
yield put(permalinkFailure(error));
|
||||
}
|
||||
};
|
||||
|
||||
const handleTogglePinRequest = function* handleTogglePinRequest({ message }) {
|
||||
try {
|
||||
yield call(togglePinMessage, message);
|
||||
yield put(togglePinSuccess());
|
||||
} catch (error) {
|
||||
yield put(togglePinFailure(error));
|
||||
}
|
||||
};
|
||||
|
||||
const root = function* root() {
|
||||
yield takeLatest(MESSAGES.REQUEST, get);
|
||||
yield takeLatest(MESSAGES.DELETE_REQUEST, handleDeleteRequest);
|
||||
yield takeLatest(MESSAGES.EDIT_REQUEST, handleEditRequest);
|
||||
yield takeLatest(MESSAGES.STAR_REQUEST, handleStarRequest);
|
||||
yield takeLatest(MESSAGES.PERMALINK_REQUEST, handlePermalinkRequest);
|
||||
yield takeLatest(MESSAGES.TOGGLE_PIN_REQUEST, handleTogglePinRequest);
|
||||
};
|
||||
export default root;
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as actions from '../actions';
|
|||
import { messagesRequest } from '../actions/messages';
|
||||
import realm from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import Message from '../containers/Message';
|
||||
import Message from '../containers/message';
|
||||
import MessageBox from '../containers/MessageBox';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue