diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js
index f2d87dd2..2b2429a3 100644
--- a/app/actions/actionsTypes.js
+++ b/app/actions/actionsTypes.js
@@ -62,10 +62,6 @@ export const MESSAGES = createRequestTypes('MESSAGES', [
'TOGGLE_STAR_REQUEST',
'TOGGLE_STAR_SUCCESS',
'TOGGLE_STAR_FAILURE',
- 'PERMALINK_REQUEST',
- 'PERMALINK_SUCCESS',
- 'PERMALINK_FAILURE',
- 'PERMALINK_CLEAR',
'TOGGLE_PIN_REQUEST',
'TOGGLE_PIN_SUCCESS',
'TOGGLE_PIN_FAILURE',
diff --git a/app/actions/index.js b/app/actions/index.js
index b597699b..8d117c71 100644
--- a/app/actions/index.js
+++ b/app/actions/index.js
@@ -32,13 +32,6 @@ export function setAllSettings(settings) {
};
}
-export function setAllPermissions(permissions) {
- return {
- type: types.SET_ALL_PERMISSIONS,
- payload: permissions
- };
-}
-
export function setCustomEmojis(emojis) {
return {
type: types.SET_CUSTOM_EMOJIS,
diff --git a/app/actions/messages.js b/app/actions/messages.js
index edaaefb1..b7b3ee69 100644
--- a/app/actions/messages.js
+++ b/app/actions/messages.js
@@ -117,33 +117,6 @@ export function toggleStarFailure() {
};
}
-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 permalinkClear() {
- return {
- type: types.MESSAGES.PERMALINK_CLEAR
- };
-}
-
export function togglePinRequest(message) {
return {
type: types.MESSAGES.TOGGLE_PIN_REQUEST,
diff --git a/app/constants/permissions.js b/app/constants/permissions.js
new file mode 100644
index 00000000..16ce1cfc
--- /dev/null
+++ b/app/constants/permissions.js
@@ -0,0 +1,17 @@
+export default [
+ 'add-user-to-any-c-room',
+ 'add-user-to-any-p-room',
+ 'add-user-to-joined-room',
+ 'archive-room',
+ 'delete-c',
+ 'delete-message',
+ 'delete-p',
+ 'edit-message',
+ 'edit-room',
+ 'force-delete-message',
+ 'mute-user',
+ 'set-react-when-readonly',
+ 'set-readonly',
+ 'unarchive-room',
+ 'view-broadcast-member-list'
+];
diff --git a/app/constants/settings.js b/app/constants/settings.js
index 8f8a714e..048aa00d 100644
--- a/app/constants/settings.js
+++ b/app/constants/settings.js
@@ -1,15 +1,80 @@
export default {
- boolean: 'valueAsBoolean',
- int: 'valueAsNumber',
- string: 'valueAsString',
- select: 'valueAsString',
- code: 'valueAsString',
- relativeUrl: 'valueAsString',
- language: 'valueAsString',
- action: 'valueAsString',
- password: 'valueAsString',
- // asset: ' Object',
- color: 'valueAsString',
- font: 'valueAsString',
- roomPick: 'valueAsString'
+ Accounts_CustomFields: {
+ type: 'valueAsString'
+ },
+ Accounts_EmailOrUsernamePlaceholder: {
+ type: 'valueAsString'
+ },
+ Accounts_NamePlaceholder: {
+ type: 'valueAsString'
+ },
+ Accounts_OAuth_Facebook: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_OAuth_Github: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_OAuth_Gitlab: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_OAuth_Google: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_OAuth_Linkedin: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_OAuth_Meteor: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_OAuth_Twitter: {
+ type: 'valueAsBoolean'
+ },
+ Accounts_PasswordPlaceholder: {
+ type: 'valueAsString'
+ },
+ Accounts_RepeatPasswordPlaceholder: {
+ type: 'valueAsString'
+ },
+ CROWD_Enable: {
+ type: 'valueAsBoolean'
+ },
+ Layout_Privacy_Policy: {
+ type: 'valueAsString'
+ },
+ Layout_Terms_of_Service: {
+ type: 'valueAsString'
+ },
+ LDAP_Enable: {
+ type: 'valueAsBoolean'
+ },
+ Message_AllowDeleting: {
+ type: 'valueAsBoolean'
+ },
+ Message_AllowDeleting_BlockDeleteInMinutes: {
+ type: 'valueAsNumber'
+ },
+ Message_AllowEditing: {
+ type: 'valueAsBoolean'
+ },
+ Message_AllowEditing_BlockEditInMinutes: {
+ type: 'valueAsNumber'
+ },
+ Message_AllowPinning: {
+ type: 'valueAsBoolean'
+ },
+ Message_AllowStarring: {
+ type: 'valueAsBoolean'
+ },
+ Message_GroupingPeriod: {
+ type: 'valueAsNumber'
+ },
+ Message_TimeFormat: {
+ type: 'valueAsString'
+ },
+ Site_Url: {
+ type: 'valueAsString'
+ },
+ Store_Last_Message: {
+ type: 'valueAsBoolean'
+ }
};
diff --git a/app/constants/types.js b/app/constants/types.js
index 3e65838c..8c5a6c8e 100644
--- a/app/constants/types.js
+++ b/app/constants/types.js
@@ -1,5 +1,4 @@
export const SET_CURRENT_SERVER = 'SET_CURRENT_SERVER';
export const SET_ALL_SETTINGS = 'SET_ALL_SETTINGS';
-export const SET_ALL_PERMISSIONS = 'SET_ALL_PERMISSIONS';
export const SET_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS';
export const ADD_SETTINGS = 'ADD_SETTINGS';
diff --git a/app/containers/MessageActions.js b/app/containers/MessageActions.js
index ee63c6ad..7dc91f02 100644
--- a/app/containers/MessageActions.js
+++ b/app/containers/MessageActions.js
@@ -9,8 +9,6 @@ import {
deleteRequest,
editInit,
toggleStarRequest,
- permalinkRequest,
- permalinkClear,
togglePinRequest,
setInput,
actionsHide,
@@ -22,11 +20,8 @@ import I18n from '../i18n';
@connect(
state => ({
- showActions: state.messages.showActions,
actionMessage: state.messages.actionMessage,
user: state.login.user,
- permissions: state.permissions,
- permalink: state.messages.permalink,
Message_AllowDeleting: state.settings.Message_AllowDeleting,
Message_AllowDeleting_BlockDeleteInMinutes: state.settings.Message_AllowDeleting_BlockDeleteInMinutes,
Message_AllowEditing: state.settings.Message_AllowEditing,
@@ -39,8 +34,6 @@ import I18n from '../i18n';
deleteRequest: message => dispatch(deleteRequest(message)),
editInit: message => dispatch(editInit(message)),
toggleStarRequest: message => dispatch(toggleStarRequest(message)),
- permalinkRequest: message => dispatch(permalinkRequest(message)),
- permalinkClear: () => dispatch(permalinkClear()),
togglePinRequest: message => dispatch(togglePinRequest(message)),
setInput: message => dispatch(setInput(message)),
toggleReactionPicker: message => dispatch(toggleReactionPicker(message))
@@ -49,19 +42,14 @@ import I18n from '../i18n';
export default class MessageActions extends React.Component {
static propTypes = {
actionsHide: PropTypes.func.isRequired,
- showActions: PropTypes.bool.isRequired,
room: PropTypes.object,
actionMessage: PropTypes.object,
user: PropTypes.object,
- permissions: PropTypes.object.isRequired,
deleteRequest: PropTypes.func.isRequired,
editInit: PropTypes.func.isRequired,
toggleStarRequest: PropTypes.func.isRequired,
- permalinkRequest: PropTypes.func.isRequired,
- permalinkClear: PropTypes.func.isRequired,
togglePinRequest: PropTypes.func.isRequired,
setInput: PropTypes.func.isRequired,
- permalink: PropTypes.string,
toggleReactionPicker: PropTypes.func.isRequired,
Message_AllowDeleting: PropTypes.bool,
Message_AllowDeleting_BlockDeleteInMinutes: PropTypes.number,
@@ -73,99 +61,70 @@ export default class MessageActions extends React.Component {
constructor(props) {
super(props);
- this.state = {
- copyPermalink: false,
- reply: false,
- quote: false
- };
this.handleActionPress = this.handleActionPress.bind(this);
- this.options = [''];
- this.setPermissions(this.props.permissions);
- }
+ this.setPermissions();
- async componentWillReceiveProps(nextProps) {
- if (nextProps.showActions !== this.props.showActions && nextProps.showActions) {
- const { actionMessage } = nextProps;
- // Cancel
- this.options = [I18n.t('Cancel')];
- this.CANCEL_INDEX = 0;
- // Reply
- if (!this.isRoomReadOnly()) {
- this.options.push(I18n.t('Reply'));
- this.REPLY_INDEX = this.options.length - 1;
- }
- // Edit
- if (this.allowEdit(nextProps)) {
- this.options.push(I18n.t('Edit'));
- this.EDIT_INDEX = this.options.length - 1;
- }
- // Permalink
- this.options.push(I18n.t('Copy_Permalink'));
- this.PERMALINK_INDEX = this.options.length - 1;
- // Copy
- this.options.push(I18n.t('Copy_Message'));
- this.COPY_INDEX = this.options.length - 1;
- // Share
- this.options.push(I18n.t('Share_Message'));
- this.SHARE_INDEX = this.options.length - 1;
- // Quote
- if (!this.isRoomReadOnly()) {
- this.options.push(I18n.t('Quote'));
- this.QUOTE_INDEX = this.options.length - 1;
- }
- // Star
- if (this.props.Message_AllowStarring) {
- this.options.push(I18n.t(actionMessage.starred ? 'Unstar' : 'Star'));
- this.STAR_INDEX = this.options.length - 1;
- }
- // Pin
- if (this.props.Message_AllowPinning) {
- this.options.push(I18n.t(actionMessage.pinned ? 'Unpin' : 'Pin'));
- this.PIN_INDEX = this.options.length - 1;
- }
- // Reaction
- if (!this.isRoomReadOnly() || this.canReactWhenReadOnly()) {
- this.options.push(I18n.t('Add_Reaction'));
- this.REACTION_INDEX = this.options.length - 1;
- }
- // Delete
- if (this.allowDelete(nextProps)) {
- this.options.push(I18n.t('Delete'));
- this.DELETE_INDEX = this.options.length - 1;
- }
- setTimeout(() => {
- this.ActionSheet.show();
- Vibration.vibrate(50);
- });
- } else if (this.props.permalink !== nextProps.permalink && nextProps.permalink) {
- // copy permalink
- if (this.state.copyPermalink) {
- this.setState({ copyPermalink: false });
- await Clipboard.setString(nextProps.permalink);
- showToast(I18n.t('Permalink_copied_to_clipboard'));
- this.props.permalinkClear();
- // quote
- } else if (this.state.quote) {
- this.setState({ quote: false });
- const msg = `[ ](${ nextProps.permalink }) `;
- this.props.setInput({ msg });
+ // Cancel
+ this.options = [I18n.t('Cancel')];
+ this.CANCEL_INDEX = 0;
- // reply
- } else if (this.state.reply) {
- this.setState({ reply: false });
- let msg = `[ ](${ nextProps.permalink }) `;
-
- // if original message wasn't sent by current user and neither from a direct room
- if (this.props.user.username !== this.props.actionMessage.u.username && this.props.room.t !== 'd') {
- msg += `@${ this.props.actionMessage.u.username } `;
- }
- this.props.setInput({ msg });
- }
+ // Reply
+ if (!this.isRoomReadOnly()) {
+ this.options.push(I18n.t('Reply'));
+ this.REPLY_INDEX = this.options.length - 1;
}
- }
- componentDidUpdate() {
- this.setPermissions(this.props.permissions);
+ // Edit
+ if (this.allowEdit(props)) {
+ this.options.push(I18n.t('Edit'));
+ this.EDIT_INDEX = this.options.length - 1;
+ }
+
+ // Permalink
+ this.options.push(I18n.t('Copy_Permalink'));
+ this.PERMALINK_INDEX = this.options.length - 1;
+
+ // Copy
+ this.options.push(I18n.t('Copy_Message'));
+ this.COPY_INDEX = this.options.length - 1;
+
+ // Share
+ this.options.push(I18n.t('Share_Message'));
+ this.SHARE_INDEX = this.options.length - 1;
+
+ // Quote
+ if (!this.isRoomReadOnly()) {
+ this.options.push(I18n.t('Quote'));
+ this.QUOTE_INDEX = this.options.length - 1;
+ }
+
+ // Star
+ if (this.props.Message_AllowStarring) {
+ this.options.push(I18n.t(props.actionMessage.starred ? 'Unstar' : 'Star'));
+ this.STAR_INDEX = this.options.length - 1;
+ }
+
+ // Pin
+ if (this.props.Message_AllowPinning) {
+ this.options.push(I18n.t(props.actionMessage.pinned ? 'Unpin' : 'Pin'));
+ this.PIN_INDEX = this.options.length - 1;
+ }
+
+ // Reaction
+ if (!this.isRoomReadOnly() || this.canReactWhenReadOnly()) {
+ this.options.push(I18n.t('Add_Reaction'));
+ this.REACTION_INDEX = this.options.length - 1;
+ }
+
+ // Delete
+ if (this.allowDelete(props)) {
+ this.options.push(I18n.t('Delete'));
+ this.DELETE_INDEX = this.options.length - 1;
+ }
+ setTimeout(() => {
+ this.ActionSheet.show();
+ Vibration.vibrate(50);
+ });
}
setPermissions() {
@@ -176,6 +135,14 @@ export default class MessageActions extends React.Component {
this.hasForceDeletePermission = result[permissions[2]];
}
+ getPermalink = async(message) => {
+ try {
+ return await RocketChat.getPermalink(message);
+ } catch (error) {
+ return null;
+ }
+ }
+
isOwn = props => props.actionMessage.u && props.actionMessage.u._id === props.user.id;
isRoomReadOnly = () => this.props.room.ro;
@@ -272,23 +239,31 @@ export default class MessageActions extends React.Component {
this.props.toggleStarRequest(this.props.actionMessage);
}
- handlePermalink() {
- this.setState({ copyPermalink: true });
- this.props.permalinkRequest(this.props.actionMessage);
+ async handlePermalink() {
+ const permalink = await this.getPermalink(this.props.actionMessage);
+ Clipboard.setString(permalink);
+ showToast(I18n.t('Permalink_copied_to_clipboard'));
}
handlePin() {
this.props.togglePinRequest(this.props.actionMessage);
}
- handleReply() {
- this.setState({ reply: true });
- this.props.permalinkRequest(this.props.actionMessage);
+ async handleReply() {
+ const permalink = await this.getPermalink(this.props.actionMessage);
+ let msg = `[ ](${ permalink }) `;
+
+ // if original message wasn't sent by current user and neither from a direct room
+ if (this.props.user.username !== this.props.actionMessage.u.username && this.props.room.t !== 'd') {
+ msg += `@${ this.props.actionMessage.u.username } `;
+ }
+ this.props.setInput({ msg });
}
- handleQuote() {
- this.setState({ quote: true });
- this.props.permalinkRequest(this.props.actionMessage);
+ async handleQuote() {
+ const permalink = await this.getPermalink(this.props.actionMessage);
+ const msg = `[ ](${ permalink }) `;
+ this.props.setInput({ msg });
}
handleReaction() {
diff --git a/app/containers/MessageErrorActions.js b/app/containers/MessageErrorActions.js
index 4a8a9eeb..3f89bf86 100644
--- a/app/containers/MessageErrorActions.js
+++ b/app/containers/MessageErrorActions.js
@@ -11,7 +11,6 @@ import I18n from '../i18n';
@connect(
state => ({
- showErrorActions: state.messages.showErrorActions,
actionMessage: state.messages.actionMessage
}),
dispatch => ({
@@ -21,7 +20,6 @@ import I18n from '../i18n';
export default class MessageErrorActions extends React.Component {
static propTypes = {
errorActionsHide: PropTypes.func.isRequired,
- showErrorActions: PropTypes.bool.isRequired,
actionMessage: PropTypes.object
};
@@ -32,12 +30,7 @@ export default class MessageErrorActions extends React.Component {
this.CANCEL_INDEX = 0;
this.DELETE_INDEX = 1;
this.RESEND_INDEX = 2;
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.showErrorActions !== this.props.showErrorActions && nextProps.showErrorActions) {
- this.ActionSheet.show();
- }
+ this.ActionSheet.show();
}
handleResend = protectedFunction(() => RocketChat.resendMessage(this.props.actionMessage._id));
diff --git a/app/containers/Routes.js b/app/containers/Routes.js
index bb20c90b..b4f0e008 100644
--- a/app/containers/Routes.js
+++ b/app/containers/Routes.js
@@ -57,6 +57,10 @@ export default class Routes extends React.Component {
NavigationService.setNavigator(this.navigator);
}
+ componentWillUnmount() {
+ Linking.removeAllListeners();
+ }
+
handleOpenURL({ url }) {
if (url) {
url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, '');
diff --git a/app/lib/methods/getPermissions.js b/app/lib/methods/getPermissions.js
index cfdc21c3..6772c775 100644
--- a/app/lib/methods/getPermissions.js
+++ b/app/lib/methods/getPermissions.js
@@ -1,26 +1,29 @@
import { InteractionManager } from 'react-native';
-import reduxStore from '../createStore';
-// import { get } from './helpers/rest';
-
import database from '../realm';
-import * as actions from '../../actions';
import log from '../../utils/log';
+import defaultPermissions from '../../constants/permissions';
-const getLastMessage = () => {
+const getLastUpdate = () => {
const setting = database.objects('permissions').sorted('_updatedAt', true)[0];
return setting && setting._updatedAt;
};
-
export default async function() {
try {
- const lastMessage = getLastMessage();
- const result = await (!lastMessage ? this.ddp.call('permissions/get') : this.ddp.call('permissions/get', new Date(lastMessage)));
- const permissions = this._preparePermissions(result.update || result);
- InteractionManager.runAfterInteractions(() => database.write(() =>
- permissions.forEach(permission => database.create('permissions', permission, true))));
- reduxStore.dispatch(actions.setAllPermissions(this.parsePermissions(permissions)));
+ const lastUpdate = getLastUpdate();
+ const result = await (!lastUpdate ? this.ddp.call('permissions/get') : this.ddp.call('permissions/get', new Date(lastUpdate)));
+ const permissions = (result.update || result).filter(permission => defaultPermissions.includes(permission._id));
+ permissions
+ .map((permission) => {
+ permission._updatedAt = new Date();
+ permission.roles = permission.roles.map(role => ({ value: role }));
+ return permission;
+ });
+
+ InteractionManager.runAfterInteractions(() =>
+ database.write(() =>
+ permissions.forEach(permission => database.create('permissions', permission, true))));
} catch (e) {
log('getPermissions', e);
}
diff --git a/app/lib/methods/getSettings.js b/app/lib/methods/getSettings.js
index 63ed4bd8..ae4fc63e 100644
--- a/app/lib/methods/getSettings.js
+++ b/app/lib/methods/getSettings.js
@@ -6,21 +6,22 @@ import database from '../realm';
import * as actions from '../../actions';
import log from '../../utils/log';
-const getLastMessage = () => {
+const getLastUpdate = () => {
const [setting] = database.objects('settings').sorted('_updatedAt', true);
return setting && setting._updatedAt;
};
export default async function() {
try {
- const lastMessage = getLastMessage();
- const result = await (!lastMessage ? this.ddp.call('public-settings/get') : this.ddp.call('public-settings/get', new Date(lastMessage)));
+ const lastUpdate = getLastUpdate();
+ const result = await (!lastUpdate ? this.ddp.call('public-settings/get') : this.ddp.call('public-settings/get', new Date(lastUpdate)));
const filteredSettings = this._prepareSettings(this._filterSettings(result.update || result));
InteractionManager.runAfterInteractions(() =>
database.write(() =>
- filteredSettings.forEach(setting => database.create('settings', setting, true))));
+ filteredSettings.forEach(setting =>
+ database.create('settings', { ...setting, _updatedAt: new Date() }, true))));
reduxStore.dispatch(actions.addSettings(this.parseSettings(filteredSettings)));
} catch (e) {
log('getSettings', e);
diff --git a/app/lib/realm.js b/app/lib/realm.js
index ee7b8464..260b160a 100644
--- a/app/lib/realm.js
+++ b/app/lib/realm.js
@@ -106,8 +106,9 @@ const subscriptionSchema = {
const usersSchema = {
name: 'users',
- primaryKey: 'username',
+ primaryKey: '_id',
properties: {
+ _id: 'string',
username: 'string',
name: { type: 'string', optional: true },
avatarVersion: { type: 'int', optional: true }
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index 42076875..715f2ff4 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -1,10 +1,10 @@
-import { AsyncStorage, Platform } from 'react-native';
+import { AsyncStorage, Platform, InteractionManager } from 'react-native';
import { hashPassword } from 'react-native-meteor/lib/utils';
import foreach from 'lodash/forEach';
import RNFetchBlob from 'react-native-fetch-blob';
import reduxStore from './createStore';
-import settingsType from '../constants/settings';
+import defaultSettings from '../constants/settings';
import messagesStatus from '../constants/messagesStatus';
import database from './realm';
import log from '../utils/log';
@@ -104,7 +104,7 @@ const RocketChat = {
reduxStore.dispatch(setActiveUser(this.activeUsers));
this._setUserTimer = null;
return this.activeUsers = {};
- }, 3000);
+ }, 5000);
const activeUser = reduxStore.getState().activeUsers[ddpMessage.id];
if (!ddpMessage.fields) {
@@ -190,16 +190,13 @@ const RocketChat = {
// we're using it only because our image cache lib doesn't support clear cache
if (ddpMessage.fields && ddpMessage.fields.eventName === 'updateAvatar') {
const { args } = ddpMessage.fields;
- database.write(() => {
+ InteractionManager.runAfterInteractions(() =>
args.forEach((arg) => {
const user = database.objects('users').filtered('username = $0', arg.username);
- if (!user.length) {
- database.create('users', { username: arg.username, avatarVersion: 0 });
- } else {
+ if (user.length > 0) {
user[0].avatarVersion += 1;
}
- });
- });
+ }));
}
});
@@ -687,27 +684,17 @@ const RocketChat = {
getPermissions,
getCustomEmoji,
parseSettings: settings => settings.reduce((ret, item) => {
- ret[item._id] = item[settingsType[item.type]] || item.valueAsString || item.valueAsNumber ||
+ ret[item._id] = item[defaultSettings[item._id].type] || item.valueAsString || item.valueAsNumber ||
item.valueAsBoolean || item.value;
return ret;
}, {}),
_prepareSettings(settings) {
return settings.map((setting) => {
- setting[settingsType[setting.type]] = setting.value;
+ setting[defaultSettings[setting._id].type] = setting.value;
return setting;
});
},
- _filterSettings: settings => settings.filter(setting => settingsType[setting.type] && setting.value),
- parsePermissions: permissions => permissions.reduce((ret, item) => {
- ret[item._id] = item.roles.reduce((roleRet, role) => [...roleRet, role.value], []);
- return ret;
- }, {}),
- _preparePermissions(permissions) {
- permissions.forEach((permission) => {
- permission.roles = permission.roles.map(role => ({ value: role }));
- });
- return permissions;
- },
+ _filterSettings: settings => settings.filter(setting => defaultSettings[setting._id] && setting.value),
parseEmojis: emojis => emojis.reduce((ret, item) => {
ret[item.name] = item.extension;
item.aliases.forEach((alias) => {
@@ -843,22 +830,26 @@ const RocketChat = {
hasPermission(permissions, rid) {
// get the room from realm
const room = database.objects('subscriptions').filtered('rid = $0', rid)[0];
+ // get permissions from realm
+ const permissionsFiltered = database.objects('permissions')
+ .filter(permission => permissions.includes(permission._id));
// get room roles
const { roles } = room;
// transform room roles to array
const roomRoles = Array.from(Object.keys(roles), i => roles[i].value);
// get user roles on the server from redux
const userRoles = reduxStore.getState().login.user.roles || [];
- // get all permissions from redux
- const allPermissions = reduxStore.getState().permissions;
// merge both roles
const mergedRoles = [...new Set([...roomRoles, ...userRoles])];
// return permissions in object format
// e.g. { 'edit-room': true, 'set-readonly': false }
return permissions.reduce((result, permission) => {
- result[permission] = returnAnArray(allPermissions[permission])
- .some(item => mergedRoles.indexOf(item) !== -1);
+ result[permission] = false;
+ const permissionFound = permissionsFiltered.find(p => p._id === permission);
+ if (permissionFound) {
+ result[permission] = returnAnArray(permissionFound.roles).some(r => mergedRoles.includes(r.value));
+ }
return result;
}, {});
},
diff --git a/app/reducers/index.js b/app/reducers/index.js
index 6f66738e..27d07f44 100644
--- a/app/reducers/index.js
+++ b/app/reducers/index.js
@@ -10,7 +10,6 @@ import navigator from './navigator';
import selectedUsers from './selectedUsers';
import createChannel from './createChannel';
import app from './app';
-import permissions from './permissions';
import customEmojis from './customEmojis';
import activeUsers from './activeUsers';
import roles from './roles';
@@ -32,7 +31,6 @@ export default combineReducers({
app,
room,
rooms,
- permissions,
customEmojis,
activeUsers,
roles,
diff --git a/app/reducers/messages.js b/app/reducers/messages.js
index ae17f395..caec481d 100644
--- a/app/reducers/messages.js
+++ b/app/reducers/messages.js
@@ -6,7 +6,6 @@ const initialState = {
message: {},
actionMessage: {},
editing: false,
- permalink: '',
showActions: false,
showErrorActions: false,
showReactionPicker: false
@@ -77,16 +76,6 @@ export default function messages(state = initialState, action) {
message: {},
editing: false
};
- case types.MESSAGES.PERMALINK_SUCCESS:
- return {
- ...state,
- permalink: action.permalink
- };
- case types.MESSAGES.PERMALINK_CLEAR:
- return {
- ...state,
- permalink: ''
- };
case types.MESSAGES.SET_INPUT:
return {
...state,
diff --git a/app/reducers/permissions.js b/app/reducers/permissions.js
deleted file mode 100644
index 58d74990..00000000
--- a/app/reducers/permissions.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as types from '../constants/types';
-
-const initialState = {
- permissions: {}
-};
-
-
-export default function permissions(state = initialState.permissions, action) {
- if (action.type === types.SET_ALL_PERMISSIONS) {
- return {
- ...state,
- ...action.payload
- };
- }
-
- if (action.type === types.ADD_PERMISSIONS) {
- return {
- ...state,
- ...action.payload
- };
- }
-
- return state;
-}
diff --git a/app/sagas/messages.js b/app/sagas/messages.js
index 0dff63c6..5792ba32 100644
--- a/app/sagas/messages.js
+++ b/app/sagas/messages.js
@@ -10,8 +10,6 @@ import {
editFailure,
toggleStarSuccess,
toggleStarFailure,
- permalinkSuccess,
- permalinkFailure,
togglePinSuccess,
togglePinFailure,
setInput
@@ -24,7 +22,6 @@ import log from '../utils/log';
const deleteMessage = message => RocketChat.deleteMessage(message);
const editMessage = message => RocketChat.editMessage(message);
const toggleStarMessage = message => RocketChat.toggleStarMessage(message);
-const getPermalink = message => RocketChat.getPermalink(message);
const togglePinMessage = message => RocketChat.togglePinMessage(message);
const get = function* get({ room }) {
@@ -68,15 +65,6 @@ const handleToggleStarRequest = function* handleToggleStarRequest({ message }) {
}
};
-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);
@@ -110,7 +98,6 @@ const root = function* root() {
yield takeLatest(MESSAGES.DELETE_REQUEST, handleDeleteRequest);
yield takeLatest(MESSAGES.EDIT_REQUEST, handleEditRequest);
yield takeLatest(MESSAGES.TOGGLE_STAR_REQUEST, handleToggleStarRequest);
- yield takeLatest(MESSAGES.PERMALINK_REQUEST, handlePermalinkRequest);
yield takeLatest(MESSAGES.TOGGLE_PIN_REQUEST, handleTogglePinRequest);
yield takeLatest(MESSAGES.REPLY_BROADCAST, handleReplyBroadcast);
};
diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js
index c3808310..0f9ceaf1 100644
--- a/app/sagas/rooms.js
+++ b/app/sagas/rooms.js
@@ -6,7 +6,7 @@ import { BACKGROUND } from 'redux-enhancer-react-native-appstate';
import * as types from '../actions/actionsTypes';
// import { roomsSuccess, roomsFailure } from '../actions/rooms';
import { addUserTyping, removeUserTyping, setLastOpen } from '../actions/room';
-import { messagesRequest } from '../actions/messages';
+import { messagesRequest, editCancel } from '../actions/messages';
import RocketChat from '../lib/rocketchat';
import database from '../lib/realm';
import * as NavigationService from '../containers/routes/NavigationService';
@@ -92,6 +92,7 @@ const watchRoomOpen = function* watchRoomOpen({ room }) {
});
cancel(thread);
sub.stop();
+ yield put(editCancel());
// subscriptions.forEach((sub) => {
// sub.unsubscribe().catch(e => alert(e));
diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js
index a95a9517..973677f2 100644
--- a/app/sagas/selectServer.js
+++ b/app/sagas/selectServer.js
@@ -26,8 +26,6 @@ const selectServer = function* selectServer({ server }) {
// yield AsyncStorage.removeItem(RocketChat.TOKEN_KEY);
const settings = database.objects('settings');
yield put(actions.setAllSettings(RocketChat.parseSettings(settings.slice(0, settings.length))));
- const permissions = database.objects('permissions');
- yield put(actions.setAllPermissions(RocketChat.parsePermissions(permissions.slice(0, permissions.length))));
const emojis = database.objects('customEmojis');
yield put(actions.setCustomEmojis(RocketChat.parseEmojis(emojis.slice(0, emojis.length))));
const roles = database.objects('roles');
diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js
index 0047354d..b0ed341e 100644
--- a/app/views/RoomInfoView/index.js
+++ b/app/views/RoomInfoView/index.js
@@ -31,7 +31,6 @@ const getRoomTitle = room => (room.t === 'd' ?
@connect(state => ({
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
user: state.login.user,
- permissions: state.permissions,
activeUsers: state.activeUsers,
Message_TimeFormat: state.settings.Message_TimeFormat,
roles: state.roles
@@ -123,8 +122,12 @@ export default class RoomInfoView extends LoggedView {
}
getFullUserData = async(username) => {
- const result = await RocketChat.subscribe('fullUserData', username);
- this.sub = result;
+ try {
+ const result = await RocketChat.subscribe('fullUserData', username);
+ this.sub = result;
+ } catch (e) {
+ log('getFullUserData', e);
+ }
}
isDirect = () => this.state.room.t === 'd';
diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js
index db86edd1..bb56f99d 100644
--- a/app/views/RoomView/index.js
+++ b/app/views/RoomView/index.js
@@ -9,7 +9,7 @@ import LoggedView from '../View';
import { List } from './ListView';
// import * as actions from '../../actions';
import { openRoom, setLastOpen } from '../../actions/room';
-import { editCancel, toggleReactionPicker, actionsShow } from '../../actions/messages';
+import { toggleReactionPicker, actionsShow } from '../../actions/messages';
import database from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import Message from '../../containers/message';
@@ -22,6 +22,7 @@ import ReactionPicker from './ReactionPicker';
import styles from './styles';
import log from '../../utils/log';
import I18n from '../../i18n';
+import debounce from '../../utils/debounce';
@connect(
state => ({
@@ -29,12 +30,14 @@ import I18n from '../../i18n';
// Message_TimeFormat: state.settings.Message_TimeFormat,
loading: state.messages.isFetching,
user: state.login.user,
- actionMessage: state.messages.actionMessage
+ actionMessage: state.messages.actionMessage,
+ showActions: state.messages.showActions,
+ showErrorActions: state.messages.showErrorActions
}),
dispatch => ({
// actions: bindActionCreators(actions, dispatch),
openRoom: room => dispatch(openRoom(room)),
- editCancel: () => dispatch(editCancel()),
+ // editCancel: () => dispatch(editCancel()),
setLastOpen: date => dispatch(setLastOpen(date)),
toggleReactionPicker: message => dispatch(toggleReactionPicker(message)),
actionsShow: actionMessage => dispatch(actionsShow(actionMessage))
@@ -46,7 +49,7 @@ export default class RoomView extends LoggedView {
openRoom: PropTypes.func.isRequired,
setLastOpen: PropTypes.func.isRequired,
user: PropTypes.object.isRequired,
- editCancel: PropTypes.func,
+ // editCancel: PropTypes.func,
rid: PropTypes.string,
name: PropTypes.string,
// Site_Url: PropTypes.string,
@@ -85,10 +88,10 @@ export default class RoomView extends LoggedView {
}
componentWillUnmount() {
this.rooms.removeAllListeners();
- this.props.editCancel();
+ this.onEndReached.stop();
}
- onEndReached = (lastRowData) => {
+ onEndReached = debounce((lastRowData) => {
if (!lastRowData) {
this.setState({ end: true });
return;
@@ -102,7 +105,7 @@ export default class RoomView extends LoggedView {
log('RoomView.onEndReached', e);
}
});
- }
+ })
onMessageLongPress = (message) => {
this.props.actionsShow(message);
@@ -186,8 +189,6 @@ export default class RoomView extends LoggedView {
/>
);
- // renderSeparator = () => ;
-
renderFooter = () => {
if (!this.state.joined) {
return (
@@ -232,8 +233,8 @@ export default class RoomView extends LoggedView {
renderRow={this.renderItem}
/>
{this.renderFooter()}
- {this.state.room._id ? : null}
-
+ {this.state.room._id && this.props.showActions ? : null}
+ {this.props.showErrorActions ? : null}
);
diff --git a/app/views/RoomsListView/Header/index.js b/app/views/RoomsListView/Header/index.js
index f9272ac2..180f455a 100644
--- a/app/views/RoomsListView/Header/index.js
+++ b/app/views/RoomsListView/Header/index.js
@@ -6,6 +6,7 @@ import { connect } from 'react-redux';
import Modal from 'react-native-modal';
import FastImage from 'react-native-fast-image';
import { HeaderBackButton } from 'react-navigation';
+import equal from 'deep-equal';
import Avatar from '../../../containers/Avatar';
import Status from '../../../containers/status';
@@ -50,7 +51,7 @@ const title = (offline, connecting, authenticating, logged) => {
setSearch: searchText => dispatch(setSearch(searchText))
}))
-export default class RoomsListHeaderView extends React.PureComponent {
+export default class RoomsListHeaderView extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired,
user: PropTypes.object.isRequired,
@@ -67,6 +68,13 @@ export default class RoomsListHeaderView extends React.PureComponent {
};
}
+ shouldComponentUpdate(nextProps) {
+ if (!equal(this.props, nextProps)) {
+ return true;
+ }
+ return false;
+ }
+
onPressModalButton(status) {
try {
RocketChat.setUserPresenceDefaultStatus(status);
diff --git a/e2e/09-roominfo.spec.js b/e2e/09-roominfo.spec.js
index 06037a7d..e4389194 100644
--- a/e2e/09-roominfo.spec.js
+++ b/e2e/09-roominfo.spec.js
@@ -318,7 +318,7 @@ describe('Room info screen', () => {
await expect(element(by.id(`rooms-list-view-item-${ room }`))).toBeNotVisible();
});
- after(async() => {
+ afterEach(async() => {
takeScreenshot();
});
});
diff --git a/package-lock.json b/package-lock.json
index 1458aa30..fa005232 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15005,7 +15005,7 @@
"integrity": "sha512-Bvq4FQPMAFijqjqNX6TxLgKOwdbruM6GvFwF9rb+mowbaFZVoYbHTKLaAbdPlrblgaZKWyOuuxBUoDx41+Xktg==",
"requires": {
"prop-types": "15.6.1",
- "react-native-animatable": "1.2.4"
+ "react-native-animatable": "1.3.0"
}
}
}