summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--web/react/components/access_history_modal.jsx2
-rw-r--r--web/react/components/activity_log_modal.jsx2
-rw-r--r--web/react/components/channel_header.jsx2
-rw-r--r--web/react/components/channel_invite_modal.jsx2
-rw-r--r--web/react/components/channel_members_modal.jsx2
-rw-r--r--web/react/components/channel_notifications.jsx2
-rw-r--r--web/react/components/delete_post_modal.jsx2
-rw-r--r--web/react/components/file_attachment.jsx2
-rw-r--r--web/react/components/more_channels.jsx2
-rw-r--r--web/react/components/navbar_dropdown.jsx2
-rw-r--r--web/react/components/notify_counts.jsx2
-rw-r--r--web/react/components/post.jsx2
-rw-r--r--web/react/components/posts_view.jsx2
-rw-r--r--web/react/components/posts_view_container.jsx2
-rw-r--r--web/react/components/rhs_comment.jsx2
-rw-r--r--web/react/components/rhs_root_post.jsx2
-rw-r--r--web/react/components/rhs_thread.jsx4
-rw-r--r--web/react/components/search_bar.jsx2
-rw-r--r--web/react/components/search_results.jsx2
-rw-r--r--web/react/components/sidebar.jsx7
-rw-r--r--web/react/components/sidebar_right.jsx4
-rw-r--r--web/react/components/team_members.jsx2
-rw-r--r--web/react/components/team_settings.jsx2
-rw-r--r--web/react/components/user_profile.jsx2
-rw-r--r--web/react/components/user_settings/user_settings.jsx2
-rw-r--r--web/react/components/user_settings/user_settings_appearance.jsx12
-rw-r--r--web/react/components/user_settings/user_settings_notifications.jsx20
-rw-r--r--web/react/utils/utils.jsx94
28 files changed, 138 insertions, 47 deletions
diff --git a/web/react/components/access_history_modal.jsx b/web/react/components/access_history_modal.jsx
index 27959ec7e..ab5686720 100644
--- a/web/react/components/access_history_modal.jsx
+++ b/web/react/components/access_history_modal.jsx
@@ -54,7 +54,7 @@ export default class AccessHistoryModal extends React.Component {
}
onAuditChange() {
var newState = this.getStateFromStoresForAudits();
- if (!Utils.areStatesEqual(newState.audits, this.state.audits)) {
+ if (!Utils.areObjectsEqual(newState.audits, this.state.audits)) {
this.setState(newState);
}
}
diff --git a/web/react/components/activity_log_modal.jsx b/web/react/components/activity_log_modal.jsx
index ef3077470..af423a601 100644
--- a/web/react/components/activity_log_modal.jsx
+++ b/web/react/components/activity_log_modal.jsx
@@ -73,7 +73,7 @@ export default class ActivityLogModal extends React.Component {
}
onListenerChange() {
const newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(newState.sessions, this.state.sessions)) {
+ if (!Utils.areObjectsEqual(newState.sessions, this.state.sessions)) {
this.setState(newState);
}
}
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx
index dcc3bf87d..a8d4ec100 100644
--- a/web/react/components/channel_header.jsx
+++ b/web/react/components/channel_header.jsx
@@ -66,7 +66,7 @@ export default class ChannelHeader extends React.Component {
}
onListenerChange() {
const newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
$('.channel-header__info .description').popover({placement: 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}});
diff --git a/web/react/components/channel_invite_modal.jsx b/web/react/components/channel_invite_modal.jsx
index 7c1032321..47bc50971 100644
--- a/web/react/components/channel_invite_modal.jsx
+++ b/web/react/components/channel_invite_modal.jsx
@@ -78,7 +78,7 @@ export default class ChannelInviteModal extends React.Component {
}
onListenerChange() {
var newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(this.state, newState)) {
+ if (!Utils.areObjectsEqual(this.state, newState)) {
this.setState(newState);
}
}
diff --git a/web/react/components/channel_members_modal.jsx b/web/react/components/channel_members_modal.jsx
index 2fa7ae8ff..5cf3511f4 100644
--- a/web/react/components/channel_members_modal.jsx
+++ b/web/react/components/channel_members_modal.jsx
@@ -91,7 +91,7 @@ export default class ChannelMembersModal extends React.Component {
}
onChange() {
const newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(this.state, newState)) {
+ if (!Utils.areObjectsEqual(this.state, newState)) {
this.setState(newState);
}
}
diff --git a/web/react/components/channel_notifications.jsx b/web/react/components/channel_notifications.jsx
index 43700bf36..f57fc12c5 100644
--- a/web/react/components/channel_notifications.jsx
+++ b/web/react/components/channel_notifications.jsx
@@ -69,7 +69,7 @@ export default class ChannelNotifications extends React.Component {
newState.notifyLevel = notifyLevel;
newState.markUnreadLevel = markUnreadLevel;
- if (!Utils.areStatesEqual(this.state, newState)) {
+ if (!Utils.areObjectsEqual(this.state, newState)) {
this.setState(newState);
}
}
diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx
index 3a3dabce5..f3bead1c2 100644
--- a/web/react/components/delete_post_modal.jsx
+++ b/web/react/components/delete_post_modal.jsx
@@ -81,7 +81,7 @@ export default class DeletePostModal extends React.Component {
}
onListenerChange() {
var newList = PostStore.getSelectedPost();
- if (!Utils.areStatesEqual(this.state.selectedList, newList)) {
+ if (!Utils.areObjectsEqual(this.state.selectedList, newList)) {
this.setState({selectedList: newList});
}
}
diff --git a/web/react/components/file_attachment.jsx b/web/react/components/file_attachment.jsx
index e707e32f5..d6a30abf9 100644
--- a/web/react/components/file_attachment.jsx
+++ b/web/react/components/file_attachment.jsx
@@ -67,7 +67,7 @@ export default class FileAttachment extends React.Component {
this.canSetState = false;
}
shouldComponentUpdate(nextProps, nextState) {
- if (!utils.areStatesEqual(nextProps, this.props)) {
+ if (!utils.areObjectsEqual(nextProps, this.props)) {
return true;
}
diff --git a/web/react/components/more_channels.jsx b/web/react/components/more_channels.jsx
index c4f831c2e..8a6dd84a4 100644
--- a/web/react/components/more_channels.jsx
+++ b/web/react/components/more_channels.jsx
@@ -46,7 +46,7 @@ export default class MoreChannels extends React.Component {
}
onListenerChange() {
var newState = getStateFromStores();
- if (!utils.areStatesEqual(newState.channels, this.state.channels)) {
+ if (!utils.areObjectsEqual(newState.channels, this.state.channels)) {
this.setState(newState);
}
}
diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx
index 0b755f377..cf9db055d 100644
--- a/web/react/components/navbar_dropdown.jsx
+++ b/web/react/components/navbar_dropdown.jsx
@@ -70,7 +70,7 @@ export default class NavbarDropdown extends React.Component {
}
onListenerChange() {
var newState = getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/notify_counts.jsx b/web/react/components/notify_counts.jsx
index 54b9e4289..0a4f60989 100644
--- a/web/react/components/notify_counts.jsx
+++ b/web/react/components/notify_counts.jsx
@@ -39,7 +39,7 @@ export default class NotifyCounts extends React.Component {
}
onListenerChange() {
var newState = getCountsStateFromStores();
- if (!utils.areStatesEqual(newState, this.state)) {
+ if (!utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx
index c3c5b3e0b..2b9586345 100644
--- a/web/react/components/post.jsx
+++ b/web/react/components/post.jsx
@@ -77,7 +77,7 @@ export default class Post extends React.Component {
this.forceUpdate();
}
shouldComponentUpdate(nextProps) {
- if (!utils.areStatesEqual(nextProps.post, this.props.post)) {
+ if (!utils.areObjectsEqual(nextProps.post, this.props.post)) {
return true;
}
diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx
index 52722aefc..087ca1df2 100644
--- a/web/react/components/posts_view.jsx
+++ b/web/react/components/posts_view.jsx
@@ -242,7 +242,7 @@ export default class PostsView extends React.Component {
if (this.props.messageSeparatorTime !== nextProps.messageSeparatorTime) {
return true;
}
- if (!Utils.areStatesEqual(this.props.postList, nextProps.postList)) {
+ if (!Utils.areObjectsEqual(this.props.postList, nextProps.postList)) {
return true;
}
diff --git a/web/react/components/posts_view_container.jsx b/web/react/components/posts_view_container.jsx
index 5037a86cd..c76c8a57e 100644
--- a/web/react/components/posts_view_container.jsx
+++ b/web/react/components/posts_view_container.jsx
@@ -223,7 +223,7 @@ export default class PostsViewContainer extends React.Component {
}
}
shouldComponentUpdate(nextProps, nextState) {
- if (Utils.areStatesEqual(this.state, nextState)) {
+ if (Utils.areObjectsEqual(this.state, nextState)) {
return false;
}
diff --git a/web/react/components/rhs_comment.jsx b/web/react/components/rhs_comment.jsx
index 8c6324c72..58cc1cac7 100644
--- a/web/react/components/rhs_comment.jsx
+++ b/web/react/components/rhs_comment.jsx
@@ -61,7 +61,7 @@ export default class RhsComment extends React.Component {
this.parseEmojis();
}
shouldComponentUpdate(nextProps) {
- if (!Utils.areStatesEqual(nextProps.post, this.props.post)) {
+ if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) {
return true;
}
diff --git a/web/react/components/rhs_root_post.jsx b/web/react/components/rhs_root_post.jsx
index e3b023841..69de5d523 100644
--- a/web/react/components/rhs_root_post.jsx
+++ b/web/react/components/rhs_root_post.jsx
@@ -26,7 +26,7 @@ export default class RhsRootPost extends React.Component {
this.parseEmojis();
}
shouldComponentUpdate(nextProps) {
- if (!utils.areStatesEqual(nextProps.post, this.props.post)) {
+ if (!utils.areObjectsEqual(nextProps.post, this.props.post)) {
return true;
}
diff --git a/web/react/components/rhs_thread.jsx b/web/react/components/rhs_thread.jsx
index fe57bed28..7c11de7cf 100644
--- a/web/react/components/rhs_thread.jsx
+++ b/web/react/components/rhs_thread.jsx
@@ -82,7 +82,7 @@ export default class RhsThread extends React.Component {
}
onChange() {
var newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
@@ -112,7 +112,7 @@ export default class RhsThread extends React.Component {
}
var newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx
index 90865475b..0f749f2cf 100644
--- a/web/react/components/search_bar.jsx
+++ b/web/react/components/search_bar.jsx
@@ -46,7 +46,7 @@ export default class SearchBar extends React.Component {
onListenerChange(doSearch, isMentionSearch) {
if (this.mounted) {
var newState = this.getSearchTermStateFromStores();
- if (!utils.areStatesEqual(newState, this.state)) {
+ if (!utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
if (doSearch) {
diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx
index b56a7b006..2f0068908 100644
--- a/web/react/components/search_results.jsx
+++ b/web/react/components/search_results.jsx
@@ -55,7 +55,7 @@ export default class SearchResults extends React.Component {
onChange() {
if (this.mounted) {
var newState = getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index e3ee9f14b..b02ec0692 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -175,7 +175,7 @@ export default class Sidebar extends React.Component {
window.addEventListener('resize', this.handleResize);
}
shouldComponentUpdate(nextProps, nextState) {
- if (!Utils.areStatesEqual(nextState, this.state)) {
+ if (!Utils.areObjectsEqual(nextState, this.state)) {
return true;
}
return false;
@@ -207,10 +207,7 @@ export default class Sidebar extends React.Component {
}
}
onChange() {
- var newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
- this.setState(newState);
- }
+ this.setState(this.getStateFromStores());
}
updateTitle() {
const channel = ChannelStore.getCurrent();
diff --git a/web/react/components/sidebar_right.jsx b/web/react/components/sidebar_right.jsx
index e2ef60959..ab558ad0f 100644
--- a/web/react/components/sidebar_right.jsx
+++ b/web/react/components/sidebar_right.jsx
@@ -66,13 +66,13 @@ export default class SidebarRight extends React.Component {
onSelectedChange(fromSearch) {
var newState = getStateFromStores(fromSearch);
newState.from_search = fromSearch;
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
onSearchChange() {
var newState = getStateFromStores();
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/team_members.jsx b/web/react/components/team_members.jsx
index ac1ebf52d..afe7f46ec 100644
--- a/web/react/components/team_members.jsx
+++ b/web/react/components/team_members.jsx
@@ -59,7 +59,7 @@ export default class TeamMembers extends React.Component {
onChange() {
var newState = getStateFromStores();
- if (!utils.areStatesEqual(newState, this.state)) {
+ if (!utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/team_settings.jsx b/web/react/components/team_settings.jsx
index 09674f1ef..862f3c528 100644
--- a/web/react/components/team_settings.jsx
+++ b/web/react/components/team_settings.jsx
@@ -23,7 +23,7 @@ export default class TeamSettings extends React.Component {
}
onChange() {
var team = TeamStore.getCurrent();
- if (!Utils.areStatesEqual(this.state.team, team)) {
+ if (!Utils.areObjectsEqual(this.state.team, team)) {
this.setState({team});
}
}
diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx
index eb0a8f0ca..8c6b1d89c 100644
--- a/web/react/components/user_profile.jsx
+++ b/web/react/components/user_profile.jsx
@@ -43,7 +43,7 @@ export default class UserProfile extends React.Component {
onChange(userId) {
if (!userId || userId === this.props.userId) {
var newState = this.getStateFromStores(this.props.userId);
- if (!Utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/components/user_settings/user_settings.jsx b/web/react/components/user_settings/user_settings.jsx
index e089ce973..40825ba93 100644
--- a/web/react/components/user_settings/user_settings.jsx
+++ b/web/react/components/user_settings/user_settings.jsx
@@ -36,7 +36,7 @@ export default class UserSettings extends React.Component {
onListenerChange() {
var user = UserStore.getCurrentUser();
- if (!utils.areStatesEqual(this.state.user, user)) {
+ if (!utils.areObjectsEqual(this.state.user, user)) {
this.setState({user});
}
}
diff --git a/web/react/components/user_settings/user_settings_appearance.jsx b/web/react/components/user_settings/user_settings_appearance.jsx
index d73b5f476..029a1af5e 100644
--- a/web/react/components/user_settings/user_settings_appearance.jsx
+++ b/web/react/components/user_settings/user_settings_appearance.jsx
@@ -1,13 +1,15 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-var UserStore = require('../../stores/user_store.jsx');
-var Client = require('../../utils/client.jsx');
-var Utils = require('../../utils/utils.jsx');
-
const CustomThemeChooser = require('./custom_theme_chooser.jsx');
const PremadeThemeChooser = require('./premade_theme_chooser.jsx');
+
+const UserStore = require('../../stores/user_store.jsx');
+
const AppDispatcher = require('../../dispatcher/app_dispatcher.jsx');
+const Client = require('../../utils/client.jsx');
+const Utils = require('../../utils/utils.jsx');
+
const Constants = require('../../utils/constants.jsx');
const ActionTypes = Constants.ActionTypes;
@@ -66,7 +68,7 @@ export default class UserSettingsAppearance extends React.Component {
onChange() {
const newState = this.getStateFromStores();
- if (!Utils.areStatesEqual(this.state, newState)) {
+ if (!Utils.areObjectsEqual(this.state, newState)) {
this.setState(newState);
}
diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx
index c6f47804f..c958bf5bc 100644
--- a/web/react/components/user_settings/user_settings_notifications.jsx
+++ b/web/react/components/user_settings/user_settings_notifications.jsx
@@ -1,16 +1,18 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-var UserStore = require('../../stores/user_store.jsx');
-var SettingItemMin = require('../setting_item_min.jsx');
-var SettingItemMax = require('../setting_item_max.jsx');
-var client = require('../../utils/client.jsx');
-var AsyncClient = require('../../utils/async_client.jsx');
-var utils = require('../../utils/utils.jsx');
+const SettingItemMin = require('../setting_item_min.jsx');
+const SettingItemMax = require('../setting_item_max.jsx');
+
+const UserStore = require('../../stores/user_store.jsx');
+
+const Client = require('../../utils/client.jsx');
+const AsyncClient = require('../../utils/async_client.jsx');
+const Utils = require('../../utils/utils.jsx');
function getNotificationsStateFromStores() {
var user = UserStore.getCurrentUser();
- var soundNeeded = !utils.isBrowserFirefox();
+ var soundNeeded = !Utils.isBrowserFirefox();
var sound = 'true';
if (user.notify_props && user.notify_props.desktop_sound) {
@@ -116,7 +118,7 @@ export default class NotificationsTab extends React.Component {
data.all = this.state.allKey.toString();
data.channel = this.state.channelKey.toString();
- client.updateUserNotifyProps(data,
+ Client.updateUserNotifyProps(data,
function success() {
this.props.updateSection('');
AsyncClient.getMe();
@@ -138,7 +140,7 @@ export default class NotificationsTab extends React.Component {
}
onListenerChange() {
var newState = getNotificationsStateFromStores();
- if (!utils.areStatesEqual(newState, this.state)) {
+ if (!Utils.areObjectsEqual(newState, this.state)) {
this.setState(newState);
}
}
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index 38f91b35f..6f3924829 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -311,8 +311,98 @@ export function escapeRegExp(string) {
return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
}
-export function areStatesEqual(state1, state2) {
- return JSON.stringify(state1) === JSON.stringify(state2);
+// Taken from http://stackoverflow.com/questions/1068834/object-comparison-in-javascript and modified slightly
+export function areObjectsEqual(x, y) {
+ let p;
+ const leftChain = [];
+ const rightChain = [];
+
+ // Remember that NaN === NaN returns false
+ // and isNaN(undefined) returns true
+ if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
+ return true;
+ }
+
+ // Compare primitives and functions.
+ // Check if both arguments link to the same object.
+ // Especially useful on step when comparing prototypes
+ if (x === y) {
+ return true;
+ }
+
+ // Works in case when functions are created in constructor.
+ // Comparing dates is a common scenario. Another built-ins?
+ // We can even handle functions passed across iframes
+ if ((typeof x === 'function' && typeof y === 'function') ||
+ (x instanceof Date && y instanceof Date) ||
+ (x instanceof RegExp && y instanceof RegExp) ||
+ (x instanceof String && y instanceof String) ||
+ (x instanceof Number && y instanceof Number)) {
+ return x.toString() === y.toString();
+ }
+
+ // At last checking prototypes as good a we can
+ if (!(x instanceof Object && y instanceof Object)) {
+ return false;
+ }
+
+ if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
+ return false;
+ }
+
+ if (x.constructor !== y.constructor) {
+ return false;
+ }
+
+ if (x.prototype !== y.prototype) {
+ return false;
+ }
+
+ // Check for infinitive linking loops
+ if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
+ return false;
+ }
+
+ // Quick checking of one object beeing a subset of another.
+ for (p in y) {
+ if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
+ return false;
+ } else if (typeof y[p] !== typeof x[p]) {
+ return false;
+ }
+ }
+
+ for (p in x) {
+ if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
+ return false;
+ } else if (typeof y[p] !== typeof x[p]) {
+ return false;
+ }
+
+ switch (typeof (x[p])) {
+ case 'object':
+ case 'function':
+
+ leftChain.push(x);
+ rightChain.push(y);
+
+ if (!areObjectsEqual(x[p], y[p])) {
+ return false;
+ }
+
+ leftChain.pop();
+ rightChain.pop();
+ break;
+
+ default:
+ if (x[p] !== y[p]) {
+ return false;
+ }
+ break;
+ }
+ }
+
+ return true;
}
export function replaceHtmlEntities(text) {