diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 29a0dd0be..6a556d555 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -27,6 +27,7 @@ export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [ 'INIT' ]); export const ROOMS = createRequestTypes('ROOMS'); +export const ROOM_ROLES = createRequestTypes('ROOM_ROLES'); export const APP = createRequestTypes('APP', ['READY', 'INIT']); export const MESSAGES = createRequestTypes('MESSAGES', [ ...defaultTypes, diff --git a/app/actions/roomRoles.js b/app/actions/roomRoles.js new file mode 100644 index 000000000..8ce5a2e42 --- /dev/null +++ b/app/actions/roomRoles.js @@ -0,0 +1,20 @@ +import * as types from './actionsTypes'; + +export function roomRolesRequest() { + return { + type: types.ROOM_ROLES.REQUEST + }; +} + +export function roomRolesSuccess(roles) { + return { + type: types.ROOM_ROLES.SUCCESS, + roles + }; +} + +export function roomRolesFailure() { + return { + type: types.ROOM_ROLES.FAILURE + }; +} diff --git a/app/containers/message/index.js b/app/containers/message/index.js index 444c8f6d0..08788ab25 100644 --- a/app/containers/message/index.js +++ b/app/containers/message/index.js @@ -5,6 +5,7 @@ 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 * as moment from 'moment'; import Card from './Card'; import User from './User'; @@ -19,11 +20,6 @@ import { } 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, @@ -48,7 +44,10 @@ const styles = StyleSheet.create({ @connect(state => ({ message: state.messages.message, permalink: state.messages.permalink, - user: state.login.user + user: state.login.user, + permissions: state.permissions, + Message_AllowEditing: state.settings.Message_AllowEditing, + Message_AllowEditing_BlockEditInMinutes: state.settings.Message_AllowEditing_BlockEditInMinutes }), dispatch => ({ deleteRequest: message => dispatch(deleteRequest(message)), editInit: message => dispatch(editInit(message)), @@ -69,6 +68,9 @@ export default class Message extends React.Component { togglePinRequest: PropTypes.func.isRequired, setInput: PropTypes.func.isRequired, user: PropTypes.object.isRequired, + permissions: PropTypes.object.isRequired, + Message_AllowEditing: PropTypes.bool, + Message_AllowEditing_BlockEditInMinutes: PropTypes.number, message: PropTypes.object, permalink: PropTypes.string } @@ -82,6 +84,16 @@ export default class Message extends React.Component { }; this.handleActionPress = this.handleActionPress.bind(this); this.showActions = this.showActions.bind(this); + + // this.options = ['Cancel', 'Reply', 'Edit', 'Permalink', 'Copy', 'Quote', 'Star Message', 'Pin Message', 'Delete']; + this.CANCEL_INDEX = 0; + this.options = ['Cancel']; + this.options.push('Reply'); + if (this.allowEdit()) { + this.addButton('Edit'); + } + this.options.push('Delete'); + this.DESTRUCTIVE_INDEX = this.options.length - 1; } async componentWillReceiveProps(nextProps) { @@ -113,6 +125,32 @@ export default class Message extends React.Component { } } + addButton = () => { + this.options.push('Edit'); + } + + allowEdit = () => { + const hasPermission = this.props.permissions['edit-message']; + const isEditAllowed = this.props.Message_AllowEditing; + const editOwn = this.props.item.u && this.props.item.u._id === this.props.user.id; + if (!(hasPermission || (isEditAllowed && editOwn))) { + return false; + } + const blockEditInMinutes = this.props.Message_AllowEditing_BlockEditInMinutes; + if (blockEditInMinutes) { + let msgTs; + if (this.props.item.ts != null) { + msgTs = moment(this.props.item.ts); + } + let currentTsDiff; + if (msgTs != null) { + currentTsDiff = moment().diff(msgTs, 'minutes'); + } + return currentTsDiff < blockEditInMinutes; + } + return true; + } + isDeleted() { return !this.props.item.msg; } @@ -206,9 +244,6 @@ export default class Message extends React.Component { // delete } else if (actionIndex === 8) { this.handleDelete(); - // reply - } else { - console.log(actionIndex, this.props.item); } } @@ -262,10 +297,10 @@ export default class Message extends React.Component { this.ActionSheet = o} - title={title} - options={options} - cancelButtonIndex={CANCEL_INDEX} - destructiveButtonIndex={DESTRUCTIVE_INDEX} + title='Messages actions' + options={this.options} + cancelButtonIndex={this.CANCEL_INDEX} + destructiveButtonIndex={this.DESTRUCTIVE_INDEX} onPress={this.handleActionPress} /> diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 1b53eb861..c0fc2ea62 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -506,6 +506,9 @@ const RocketChat = { return resolve(result[0]); }); }, + getRoomRoles(rid) { + return call('getRoomRoles', { rid }); + }, async getPermalink(message) { return new Promise(async(resolve, reject) => { let room; diff --git a/app/reducers/messages.js b/app/reducers/messages.js index a2363bdca..6ef193baf 100644 --- a/app/reducers/messages.js +++ b/app/reducers/messages.js @@ -39,6 +39,12 @@ export default function messages(state = initialState, action) { message: {}, editing: false }; + case types.MESSAGES.EDIT_FAILURE: + return { + ...state, + message: {}, + editing: false + }; case types.MESSAGES.PERMALINK_SUCCESS: return { ...state, diff --git a/app/reducers/roomRoles.js b/app/reducers/roomRoles.js new file mode 100644 index 000000000..04a33bec3 --- /dev/null +++ b/app/reducers/roomRoles.js @@ -0,0 +1,33 @@ +import * as types from '../actions/actionsTypes'; + +const initialState = { + isFetching: false, + failure: false, + roles: [] +}; + +export default function login(state = initialState, action) { + switch (action.type) { + case types.ROOM_ROLES.REQUEST: + return { + ...state, + isFetching: true, + roles: [] + }; + case types.ROOM_ROLES.SUCCESS: + return { + ...state, + isFetching: false, + roles: action.roles + }; + case types.ROOM_ROLES.FAILURE: + return { + ...state, + isFetching: false, + failure: true, + roles: [] + }; + default: + return state; + } +}