WIP fix for image load popping

This commit is contained in:
Matthew Hodgson 2016-03-24 00:13:32 +00:00
parent b81d901919
commit 151a9994ba
4 changed files with 51 additions and 21 deletions

View file

@ -16,6 +16,7 @@ limitations under the License.
var React = require('react'); var React = require('react');
var ReactDOM = require("react-dom"); var ReactDOM = require("react-dom");
var dis = require("../../dispatcher");
var sdk = require('../../index'); var sdk = require('../../index');
/* (almost) stateless UI component which builds the event tiles in the room timeline. /* (almost) stateless UI component which builds the event tiles in the room timeline.
@ -301,8 +302,7 @@ module.exports = React.createClass({
ref={this._collectEventNode.bind(this, eventId)} ref={this._collectEventNode.bind(this, eventId)}
data-scroll-token={scrollToken}> data-scroll-token={scrollToken}>
<EventTile mxEvent={mxEv} continuation={continuation} <EventTile mxEvent={mxEv} continuation={continuation}
last={last} isSelectedEvent={highlight} last={last} isSelectedEvent={highlight} />
onImageLoad={this._onImageLoad} />
</li> </li>
); );
@ -368,14 +368,8 @@ module.exports = React.createClass({
this.eventNodes[eventId] = node; this.eventNodes[eventId] = node;
}, },
onResize: function() {
// once images in the events load, make the scrollPanel check the dis.dispatch({ action: 'timeline_resize' });
// scroll offsets.
_onImageLoad: function() {
var scrollPanel = this.refs.scrollPanel;
if (scrollPanel) {
scrollPanel.checkScroll();
}
}, },
render: function() { render: function() {
@ -392,6 +386,7 @@ module.exports = React.createClass({
return ( return (
<ScrollPanel ref="scrollPanel" className="mx_RoomView_messagePanel" <ScrollPanel ref="scrollPanel" className="mx_RoomView_messagePanel"
onScroll={ this.props.onScroll } onScroll={ this.props.onScroll }
onResize={ this.onResize }
onFillRequest={ this.props.onFillRequest } onFillRequest={ this.props.onFillRequest }
style={ this.props.hidden ? { display: 'none' } : {} } style={ this.props.hidden ? { display: 'none' } : {} }
stickyBottom={ this.props.stickyBottom }> stickyBottom={ this.props.stickyBottom }>

View file

@ -485,6 +485,10 @@ module.exports = React.createClass({
} }
}, },
onSearchResultsResize: function() {
dis.dispatch({ action: 'timeline_resize' });
},
onSearchResultsFillRequest: function(backwards) { onSearchResultsFillRequest: function(backwards) {
if (!backwards) if (!backwards)
return q(false); return q(false);
@ -1361,7 +1365,7 @@ module.exports = React.createClass({
if (this.state.searchResults) { if (this.state.searchResults) {
searchResultsPanel = ( searchResultsPanel = (
<ScrollPanel ref="searchResultsPanel" className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel" <ScrollPanel ref="searchResultsPanel" className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel"
onFillRequest={ this.onSearchResultsFillRequest }> onFillRequest={ this.onSearchResultsFillRequest } onResize={ this.onSearchResultsResize }>
<li className={scrollheader_classes}></li> <li className={scrollheader_classes}></li>
{this.getSearchResultTiles()} {this.getSearchResultTiles()}
</ScrollPanel> </ScrollPanel>

View file

@ -94,6 +94,11 @@ module.exports = React.createClass({
*/ */
onScroll: React.PropTypes.func, onScroll: React.PropTypes.func,
/* onResize: a callback which is called whenever the Gemini scroll
* panel is resized
*/
onResize: React.PropTypes.func,
/* className: classnames to add to the top-level div /* className: classnames to add to the top-level div
*/ */
className: React.PropTypes.string, className: React.PropTypes.string,
@ -181,6 +186,11 @@ module.exports = React.createClass({
this.checkFillState(); this.checkFillState();
}, },
onResize: function() {
this.props.onResize();
this.checkScroll();
},
// after an update to the contents of the panel, check that the scroll is // 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. // where it ought to be, and set off pagination requests if necessary.
checkScroll: function() { checkScroll: function() {
@ -481,7 +491,7 @@ module.exports = React.createClass({
// reflect the fact that we don't necessarily contain a list of messages. // reflect the fact that we don't necessarily contain a list of messages.
// it's not obvious why we have a separate div and ol anyway. // it's not obvious why we have a separate div and ol anyway.
return (<GeminiScrollbar autoshow={true} ref="geminiPanel" return (<GeminiScrollbar autoshow={true} ref="geminiPanel"
onScroll={this.onScroll} onResize={this.checkScroll} onScroll={this.onScroll} onResize={this.onResize}
className={this.props.className} style={this.props.style}> className={this.props.className} style={this.props.style}>
<div className="mx_RoomView_messageListWrapper"> <div className="mx_RoomView_messageListWrapper">
<ol ref="itemlist" className="mx_RoomView_MessageList" aria-live="polite"> <ol ref="itemlist" className="mx_RoomView_MessageList" aria-live="polite">

View file

@ -105,24 +105,45 @@ module.exports = React.createClass({
return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600); return MatrixClientPeg.get().mxcUrlToHttp(content.url, 800, 600);
}, },
componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
this.fixupHeight();
},
componentWillUnmount: function() {
dis.unregister(this.dispatcherRef);
},
onAction: function(payload) {
if (payload.action === "timeline_resize") {
this.fixupHeight();
}
},
fixupHeight: function() {
var content = this.props.mxEvent.getContent();
var thumbHeight = null;
var timelineWidth = this._body.offsetWidth;
var maxHeight = 600*timelineWidth/800;
//console.log("trying to fit image into timelineWidth of " + this._body.offsetWidth + " or " + this._body.clientWidth);
if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight);
this._image.style.height = thumbHeight + "px";
},
render: function() { render: function() {
var TintableSvg = sdk.getComponent("elements.TintableSvg"); var TintableSvg = sdk.getComponent("elements.TintableSvg");
var content = this.props.mxEvent.getContent(); var content = this.props.mxEvent.getContent();
var cli = MatrixClientPeg.get(); var cli = MatrixClientPeg.get();
var thumbHeight = null;
if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, 800, 600);
var imgStyle = {};
if (thumbHeight) imgStyle['maxHeight'] = thumbHeight;
var thumbUrl = this._getThumbUrl(); var thumbUrl = this._getThumbUrl();
if (thumbUrl) { if (thumbUrl) {
return ( return (
<span className="mx_MImageBody"> <span className="mx_MImageBody" ref={(c) => this._body = c}>
<a href={cli.mxcUrlToHttp(content.url)} onClick={ this.onClick }> <a href={cli.mxcUrlToHttp(content.url)} onClick={ this.onClick }>
<img className="mx_MImageBody_thumbnail" src={thumbUrl} <img className="mx_MImageBody_thumbnail" src={thumbUrl} ref={(c) => this._image = c}
alt={content.body} style={imgStyle} alt={content.body}
onMouseEnter={this.onImageEnter} onMouseEnter={this.onImageEnter}
onMouseLeave={this.onImageLeave} onMouseLeave={this.onImageLeave}
onLoad={this.props.onImageLoad} /> onLoad={this.props.onImageLoad} />