diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 807eae5dc6..698b1073d0 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -225,7 +225,8 @@ module.exports = React.createClass({ ref={this._collectEventNode.bind(this, eventId)} data-scroll-token={scrollToken}> + last={last} isSelectedEvent={highlight} + onImageLoad={this._onImageLoad} /> ); @@ -278,6 +279,16 @@ module.exports = React.createClass({ this.eventNodes[eventId] = node; }, + + // once images in the events load, make the scrollPanel check the + // scroll offsets. + _onImageLoad: function() { + var scrollPanel = this.refs.messagePanel; + if (scrollPanel) { + scrollPanel.checkScroll(); + } + }, + render: function() { var ScrollPanel = sdk.getComponent("structures.ScrollPanel"); return ( diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 6acd43a25d..56cd8d3fce 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -722,6 +722,15 @@ module.exports = React.createClass({ } } + // once images in the search results load, make the scrollPanel check + // the scroll offsets. + var onImageLoad = () => { + var scrollPanel = this.refs.searchResultsPanel; + if (scrollPanel) { + scrollPanel.checkScroll(); + } + } + var lastRoomId; for (var i = this.state.searchResults.results.length - 1; i >= 0; i--) { @@ -758,7 +767,8 @@ module.exports = React.createClass({ ret.push(); + resultLink={resultLink} + onImageLoad={onImageLoad}/>); } return ret; }, diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 514937f877..044ef48687 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -124,10 +124,9 @@ module.exports = React.createClass({ // after adding event tiles, we may need to tweak the scroll (either to // keep at the bottom of the timeline, or to maintain the view after // adding events to the top). - this._restoreSavedScrollState(); - - // we also re-check the fill state, in case the paginate was inadequate - this.checkFillState(); + // + // This will also re-check the fill state, in case the paginate was inadequate + this.checkScroll(); }, componentWillUnmount: function() { @@ -178,6 +177,13 @@ module.exports = React.createClass({ this.checkFillState(); }, + // after an update to the contents of the panel, check that the scroll is + // where it ought to be, and set off pagination requests if necessary. + checkScroll: function() { + this._restoreSavedScrollState(); + this.checkFillState(); + }, + // return true if the content is fully scrolled down right now; else false. // // note that this is independent of the 'stuckAtBottom' state - it is simply diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index b54a51c45b..b60098295a 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -27,6 +27,14 @@ var dis = require("../../../dispatcher"); module.exports = React.createClass({ displayName: 'MImageBody', + propTypes: { + /* the MatrixEvent to show */ + mxEvent: React.PropTypes.object.isRequired, + + /* callback called when images in events are loaded */ + onImageLoad: React.PropTypes.func, + }, + thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) { if (!fullWidth || !fullHeight) { // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even @@ -116,7 +124,8 @@ module.exports = React.createClass({ {content.body} + onMouseLeave={this.onImageLeave} + onLoad={this.props.onImageLoad} />
diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 9cc0e22c59..34d6d53924 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -37,6 +37,9 @@ module.exports = React.createClass({ /* link URL for the highlights */ highlightLink: React.PropTypes.string, + + /* callback called when images in events are loaded */ + onImageLoad: React.PropTypes.func, }, @@ -60,6 +63,7 @@ module.exports = React.createClass({ } return ; + highlightLink={this.props.highlightLink} + onImageLoad={this.props.onImageLoad} />; }, }); diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 0205062f84..8ac7ab7996 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -102,6 +102,9 @@ module.exports = React.createClass({ /* is this the focussed event */ isSelectedEvent: React.PropTypes.bool, + + /* callback called when images in events are loaded */ + onImageLoad: React.PropTypes.func, }, getInitialState: function() { @@ -323,7 +326,8 @@ module.exports = React.createClass({ { sender }
+ highlightLink={this.props.highlightLink} + onImageLoad={this.props.onImageLoad} />
); diff --git a/src/components/views/rooms/SearchResultTile.js b/src/components/views/rooms/SearchResultTile.js index 9c793e8705..1fc0384433 100644 --- a/src/components/views/rooms/SearchResultTile.js +++ b/src/components/views/rooms/SearchResultTile.js @@ -31,6 +31,8 @@ module.exports = React.createClass({ // href for the highlights in this result resultLink: React.PropTypes.string, + + onImageLoad: React.PropTypes.func, }, render: function() { @@ -53,7 +55,8 @@ module.exports = React.createClass({ } if (EventTile.haveTileForEvent(ev)) { ret.push(); + highlightLink={this.props.resultLink} + onImageLoad={this.props.onImageLoad} />); } } return (