fix up scroll behaviour when loading widgets
This commit is contained in:
parent
62d04c38ef
commit
4388334e30
8 changed files with 55 additions and 44 deletions
|
@ -302,6 +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}
|
||||||
|
onWidgetLoad={this._onWidgetLoad}
|
||||||
last={last} isSelectedEvent={highlight} />
|
last={last} isSelectedEvent={highlight} />
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
@ -368,6 +369,15 @@ module.exports = React.createClass({
|
||||||
this.eventNodes[eventId] = node;
|
this.eventNodes[eventId] = node;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// once dynamic content in the events load, make the scrollPanel check the
|
||||||
|
// scroll offsets.
|
||||||
|
_onWidgetLoad: function() {
|
||||||
|
var scrollPanel = this.refs.scrollPanel;
|
||||||
|
if (scrollPanel) {
|
||||||
|
scrollPanel.checkScroll();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onResize: function() {
|
onResize: function() {
|
||||||
dis.dispatch({ action: 'timeline_resize' }, true);
|
dis.dispatch({ action: 'timeline_resize' }, true);
|
||||||
},
|
},
|
||||||
|
|
|
@ -798,9 +798,9 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// once images in the search results load, make the scrollPanel check
|
// once dynamic content in the search results load, make the scrollPanel check
|
||||||
// the scroll offsets.
|
// the scroll offsets.
|
||||||
var onImageLoad = () => {
|
var onWidgetLoad = () => {
|
||||||
var scrollPanel = this.refs.searchResultsPanel;
|
var scrollPanel = this.refs.searchResultsPanel;
|
||||||
if (scrollPanel) {
|
if (scrollPanel) {
|
||||||
scrollPanel.checkScroll();
|
scrollPanel.checkScroll();
|
||||||
|
@ -844,7 +844,7 @@ module.exports = React.createClass({
|
||||||
searchResult={result}
|
searchResult={result}
|
||||||
searchHighlights={this.state.searchHighlights}
|
searchHighlights={this.state.searchHighlights}
|
||||||
resultLink={resultLink}
|
resultLink={resultLink}
|
||||||
onImageLoad={onImageLoad}/>);
|
onWidgetLoad={onWidgetLoad}/>);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,7 @@ var React = require('react');
|
||||||
var filesize = require('filesize');
|
var filesize = require('filesize');
|
||||||
|
|
||||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
|
var ImageUtils = require('../../../ImageUtils');
|
||||||
var Modal = require('../../../Modal');
|
var Modal = require('../../../Modal');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var dis = require("../../../dispatcher");
|
var dis = require("../../../dispatcher");
|
||||||
|
@ -32,29 +33,7 @@ module.exports = React.createClass({
|
||||||
mxEvent: React.PropTypes.object.isRequired,
|
mxEvent: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
/* callback called when images in events are loaded */
|
/* callback called when images in events are loaded */
|
||||||
onImageLoad: React.PropTypes.func,
|
onWidgetLoad: 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
|
|
||||||
// log this because it's spammy
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
|
|
||||||
// no scaling needs to be applied
|
|
||||||
return fullHeight;
|
|
||||||
}
|
|
||||||
var widthMulti = thumbWidth / fullWidth;
|
|
||||||
var heightMulti = thumbHeight / fullHeight;
|
|
||||||
if (widthMulti < heightMulti) {
|
|
||||||
// width is the dominant dimension so scaling will be fixed on that
|
|
||||||
return Math.floor(widthMulti * fullHeight);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// height is the dominant dimension so scaling will be fixed on that
|
|
||||||
return Math.floor(heightMulti * fullHeight);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick: function onClick(ev) {
|
onClick: function onClick(ev) {
|
||||||
|
@ -134,7 +113,9 @@ module.exports = React.createClass({
|
||||||
// the alternative here would be 600*timelineWidth/800; to scale them down to fit inside a 4:3 bounding box
|
// the alternative here would be 600*timelineWidth/800; to scale them down to fit inside a 4:3 bounding box
|
||||||
|
|
||||||
//console.log("trying to fit image into timelineWidth of " + this.refs.body.offsetWidth + " or " + this.refs.body.clientWidth);
|
//console.log("trying to fit image into timelineWidth of " + this.refs.body.offsetWidth + " or " + this.refs.body.clientWidth);
|
||||||
if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight);
|
if (content.info) {
|
||||||
|
thumbHeight = ImageUtils.thumbHeight(content.info.w, content.info.h, timelineWidth, maxHeight);
|
||||||
|
}
|
||||||
this.refs.image.style.height = thumbHeight + "px";
|
this.refs.image.style.height = thumbHeight + "px";
|
||||||
// console.log("Image height now", thumbHeight);
|
// console.log("Image height now", thumbHeight);
|
||||||
},
|
},
|
||||||
|
@ -152,8 +133,7 @@ module.exports = React.createClass({
|
||||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
||||||
alt={content.body}
|
alt={content.body}
|
||||||
onMouseEnter={this.onImageEnter}
|
onMouseEnter={this.onImageEnter}
|
||||||
onMouseLeave={this.onImageLeave}
|
onMouseLeave={this.onImageLeave} />
|
||||||
onLoad={this.props.onImageLoad} />
|
|
||||||
</a>
|
</a>
|
||||||
<div className="mx_MImageBody_download">
|
<div className="mx_MImageBody_download">
|
||||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
||||||
|
|
|
@ -39,7 +39,7 @@ module.exports = React.createClass({
|
||||||
highlightLink: React.PropTypes.string,
|
highlightLink: React.PropTypes.string,
|
||||||
|
|
||||||
/* callback called when images in events are loaded */
|
/* callback called when images in events are loaded */
|
||||||
onImageLoad: React.PropTypes.func,
|
onWidgetLoad: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,6 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
return <TileType mxEvent={this.props.mxEvent} highlights={this.props.highlights}
|
return <TileType mxEvent={this.props.mxEvent} highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
onImageLoad={this.props.onImageLoad} />;
|
onWidgetLoad={this.props.onWidgetLoad} />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -38,6 +38,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
/* link URL for the highlights */
|
/* link URL for the highlights */
|
||||||
highlightLink: React.PropTypes.string,
|
highlightLink: React.PropTypes.string,
|
||||||
|
|
||||||
|
/* callback for when our widget has loaded */
|
||||||
|
onWidgetLoad: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -88,7 +91,7 @@ module.exports = React.createClass({
|
||||||
var widget;
|
var widget;
|
||||||
if (this.state.link) {
|
if (this.state.link) {
|
||||||
var LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
|
var LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
|
||||||
widget = <LinkPreviewWidget link={ this.state.link }/>;
|
widget = <LinkPreviewWidget link={ this.state.link } onWidgetLoad={ this.props.onWidgetLoad }/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (content.msgtype) {
|
switch (content.msgtype) {
|
||||||
|
|
|
@ -105,8 +105,8 @@ module.exports = React.createClass({
|
||||||
/* is this the focused event */
|
/* is this the focused event */
|
||||||
isSelectedEvent: React.PropTypes.bool,
|
isSelectedEvent: React.PropTypes.bool,
|
||||||
|
|
||||||
/* callback called when images in events are loaded */
|
/* callback called when dynamic content in events are loaded */
|
||||||
onImageLoad: React.PropTypes.func,
|
onWidgetLoad: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -345,7 +345,7 @@ module.exports = React.createClass({
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
<EventTileType mxEvent={this.props.mxEvent} highlights={this.props.highlights}
|
<EventTileType mxEvent={this.props.mxEvent} highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
onImageLoad={this.props.onImageLoad} />
|
onWidgetLoad={this.props.onWidgetLoad} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
|
|
||||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
|
var ImageUtils = require('../../../ImageUtils');
|
||||||
|
|
||||||
var linkify = require('linkifyjs');
|
var linkify = require('linkifyjs');
|
||||||
var linkifyElement = require('linkifyjs/element');
|
var linkifyElement = require('linkifyjs/element');
|
||||||
|
@ -29,7 +30,8 @@ module.exports = React.createClass({
|
||||||
displayName: 'LinkPreviewWidget',
|
displayName: 'LinkPreviewWidget',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
link: React.PropTypes.string.isRequired
|
link: React.PropTypes.string.isRequired,
|
||||||
|
onWidgetLoad: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -41,6 +43,7 @@ module.exports = React.createClass({
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
MatrixClientPeg.get().getUrlPreview(this.props.link).then((res)=>{
|
MatrixClientPeg.get().getUrlPreview(this.props.link).then((res)=>{
|
||||||
this.setState({ preview: res });
|
this.setState({ preview: res });
|
||||||
|
this.props.onWidgetLoad();
|
||||||
}, (error)=>{
|
}, (error)=>{
|
||||||
console.error("Failed to get preview for " + this.props.link + " " + error);
|
console.error("Failed to get preview for " + this.props.link + " " + error);
|
||||||
});
|
});
|
||||||
|
@ -59,13 +62,28 @@ module.exports = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var p = this.state.preview;
|
var p = this.state.preview;
|
||||||
if (!p) return <div/>;
|
if (!p) return <div/>;
|
||||||
var img = p["og:image"]
|
|
||||||
if (img && img.startsWith("mxc://")) img = MatrixClientPeg.get().mxcUrlToHttp(img, 100, 100)
|
var image = p["og:image"];
|
||||||
|
var imageMaxWidth = 100, imageMaxHeight = 100;
|
||||||
|
if (image && image.startsWith("mxc://")) {
|
||||||
|
image = MatrixClientPeg.get().mxcUrlToHttp(image, imageMaxWidth, imageMaxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
var thumbHeight = imageMaxHeight;
|
||||||
|
if (p["og:image:width"] && p["og:image:height"]) {
|
||||||
|
thumbHeight = ImageUtils.thumbHeight(p["og:image:width"], p["og:image:height"], imageMaxWidth, imageMaxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
var img;
|
||||||
|
if (image) {
|
||||||
|
img = <div className="mx_LinkPreviewWidget_image" style={{ height: thumbHeight }}>
|
||||||
|
<a href={ this.props.link } target="_blank"><img style={{ maxWidth: imageMaxWidth, maxHeight: imageMaxHeight }} src={ image }/></a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_LinkPreviewWidget">
|
<div className="mx_LinkPreviewWidget" >
|
||||||
<div className="mx_LinkPreviewWidget_image">
|
{ img }
|
||||||
<a href={ this.props.link } target="_blank"><img style={{ maxWidth: 100, maxHeight: 100 }} src={ img }/></a>
|
|
||||||
</div>
|
|
||||||
<div className="mx_LinkPreviewWidget_caption">
|
<div className="mx_LinkPreviewWidget_caption">
|
||||||
<div className="mx_LinkPreviewWidget_title"><a href={ this.props.link } target="_blank">{ p["og:title"] }</a></div>
|
<div className="mx_LinkPreviewWidget_title"><a href={ this.props.link } target="_blank">{ p["og:title"] }</a></div>
|
||||||
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
|
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
|
||||||
|
|
|
@ -32,7 +32,7 @@ module.exports = React.createClass({
|
||||||
// href for the highlights in this result
|
// href for the highlights in this result
|
||||||
resultLink: React.PropTypes.string,
|
resultLink: React.PropTypes.string,
|
||||||
|
|
||||||
onImageLoad: React.PropTypes.func,
|
onWidgetLoad: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -56,7 +56,7 @@ module.exports = React.createClass({
|
||||||
if (EventTile.haveTileForEvent(ev)) {
|
if (EventTile.haveTileForEvent(ev)) {
|
||||||
ret.push(<EventTile key={eventId+"+"+j} mxEvent={ev} contextual={contextual} highlights={highlights}
|
ret.push(<EventTile key={eventId+"+"+j} mxEvent={ev} contextual={contextual} highlights={highlights}
|
||||||
highlightLink={this.props.resultLink}
|
highlightLink={this.props.resultLink}
|
||||||
onImageLoad={this.props.onImageLoad} />);
|
onWidgetLoad={this.props.onWidgetLoad} />);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in a new issue