diff --git a/src/ObjectUtils.js b/src/ObjectUtils.js index 41dc34cca7..07a16df501 100644 --- a/src/ObjectUtils.js +++ b/src/ObjectUtils.js @@ -77,3 +77,34 @@ module.exports.getKeyValueArrayDiffs = function(before, after) { return results; }; + +/** + * Shallow-compare two objects for equality: each key and value must be + * identical + */ +module.exports.shallowEqual = function(objA, objB) { + if (objA === objB) { + return true; + } + + if (typeof objA !== 'object' || objA === null || + typeof objB !== 'object' || objB === null) { + return false; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + for (var i = 0; i < keysA.length; i++) { + var key = keysA[i]; + if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) { + return false; + } + } + + return true; +}; diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index e3d60ed83b..84ad8f595c 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -38,6 +38,7 @@ var SlashCommands = require("../../SlashCommands"); var dis = require("../../dispatcher"); var Tinter = require("../../Tinter"); var rate_limited_func = require('../../ratelimitedfunc'); +var ObjectUtils = require('../../ObjectUtils'); var DEBUG = false; @@ -164,6 +165,11 @@ module.exports = React.createClass({ } }, + shouldComponentUpdate: function(nextProps, nextState) { + return (!ObjectUtils.shallowEqual(this.props, nextProps) || + !ObjectUtils.shallowEqual(this.state, nextState)); + }, + componentWillUnmount: function() { // set a boolean to say we've been unmounted, which any pending // promises can use to throw away their results. @@ -985,10 +991,10 @@ module.exports = React.createClass({ // but it's better than the video going missing entirely if (auxPanelMaxHeight < 50) auxPanelMaxHeight = 50; - // we may need to resize the gemini panel after changing the aux panel - // size, so add a callback to onChildResize. - this.setState({auxPanelMaxHeight: auxPanelMaxHeight}, - this.onChildResize); + this.setState({auxPanelMaxHeight: auxPanelMaxHeight}); + + // changing the maxHeight on the auxpanel will trigger a callback go + // onChildResize, so no need to worry about that here. }, onFullscreenClick: function() { @@ -1036,8 +1042,15 @@ module.exports = React.createClass({ // XXX: this is a bit naughty; we should be doing this via props if (show) { this.setState({editingRoomSettings: true}); - var self = this; - setTimeout(function() { self.onResize() }, 0); + } + }, + + // this has to be a proper method rather than an unnamed function, + // otherwise react calls it with null on each update. + _gatherTimelinePanelRef: function(r) { + this.refs.messagePanel = r; + if(r) { + this.updateTint(); } }, @@ -1200,7 +1213,7 @@ module.exports = React.createClass({ draggingFile={this.state.draggingFile} displayConfCallNotification={this.state.displayConfCallNotification} maxHeight={this.state.auxPanelMaxHeight} - onCallViewVideoRezize={this.onChildResize} > + onResize={this.onChildResize} > { aux } ); @@ -1279,12 +1292,7 @@ module.exports = React.createClass({ } var messagePanel = ( - { - this.refs.messagePanel = r; - if(r) { - this.updateTint(); - } - }} +