mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-18 06:35:35 +08:00
Put direct-linked events and search clickthroughs in the middle
We need two modes of operation for ScrollPanel.scrollToToken: For jump-to-read-marker, we want it 1/3 of the way down the screen. For search clickthrough, and hyperlinked events, we want put the event in the *middle* of the screen. Fixes https://github.com/vector-im/vector-web/issues/1032
This commit is contained in:
parent
7660276b54
commit
3fd066c2d4
@ -141,13 +141,17 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
/* jump to the given event id.
|
/* jump to the given event id.
|
||||||
*
|
*
|
||||||
* pixelOffset gives the number of pixels between the bottom of the node
|
* offsetBase gives the reference point for the pixelOffset. 0 means the
|
||||||
* and the bottom of the container. If undefined, it will put the node
|
* top of the container, 1 means the bottom, and fractional values mean
|
||||||
* 1/3 of the way down of the container.
|
* somewhere in the middle. If omitted, it defaults to 0.
|
||||||
|
*
|
||||||
|
* pixelOffset gives the number of pixels *above* the offsetBase that the
|
||||||
|
* node (specifically, the bottom of it) will be positioned. If omitted, it
|
||||||
|
* defaults to 0.
|
||||||
*/
|
*/
|
||||||
scrollToEvent: function(eventId, pixelOffset) {
|
scrollToEvent: function(eventId, pixelOffset, offsetBase) {
|
||||||
if (this.refs.scrollPanel) {
|
if (this.refs.scrollPanel) {
|
||||||
this.refs.scrollPanel.scrollToToken(eventId, pixelOffset);
|
this.refs.scrollPanel.scrollToToken(eventId, pixelOffset, offsetBase);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -326,16 +326,24 @@ module.exports = React.createClass({
|
|||||||
this._saveScrollState();
|
this._saveScrollState();
|
||||||
},
|
},
|
||||||
|
|
||||||
// pixelOffset gives the number of pixels between the bottom of the node
|
/* Scroll the panel to bring the DOM node with the scroll token
|
||||||
// and the bottom of the container. If undefined, it will put the node
|
* `scrollToken` into view.
|
||||||
// 1/3 of the way down the container.
|
*
|
||||||
scrollToToken: function(scrollToken, pixelOffset) {
|
* offsetBase gives the reference point for the pixelOffset. 0 means the
|
||||||
var scrollNode = this._getScrollNode();
|
* top of the container, 1 means the bottom, and fractional values mean
|
||||||
|
* somewhere in the middle. If omitted, it defaults to 0.
|
||||||
|
*
|
||||||
|
* pixelOffset gives the number of pixels *above* the offsetBase that the
|
||||||
|
* node (specifically, the bottom of it) will be positioned. If omitted, it
|
||||||
|
* defaults to 0.
|
||||||
|
*/
|
||||||
|
scrollToToken: function(scrollToken, pixelOffset, offsetBase) {
|
||||||
|
pixelOffset = pixelOffset || 0;
|
||||||
|
offsetBase = offsetBase || 0;
|
||||||
|
|
||||||
// default to 1/3 of the way down
|
// convert pixelOffset so that it is based on the bottom of the
|
||||||
if (pixelOffset === undefined) {
|
// container.
|
||||||
pixelOffset = (scrollNode.clientHeight * 2)/ 3;
|
pixelOffset += this._getScrollNode().clientHeight * (1-offsetBase);
|
||||||
}
|
|
||||||
|
|
||||||
// save the desired scroll state. It's important we do this here rather
|
// save the desired scroll state. It's important we do this here rather
|
||||||
// than as a result of the scroll event, because (a) we might not *get*
|
// than as a result of the scroll event, because (a) we might not *get*
|
||||||
|
@ -70,7 +70,7 @@ var TimelinePanel = React.createClass({
|
|||||||
|
|
||||||
// where to position the event given by eventId, in pixels from the
|
// where to position the event given by eventId, in pixels from the
|
||||||
// bottom of the viewport. If not given, will try to put the event
|
// bottom of the viewport. If not given, will try to put the event
|
||||||
// 1/3 of the way down the viewport.
|
// half way down the viewport.
|
||||||
eventPixelOffset: React.PropTypes.number,
|
eventPixelOffset: React.PropTypes.number,
|
||||||
|
|
||||||
// callback which is called when the panel is scrolled.
|
// callback which is called when the panel is scrolled.
|
||||||
@ -413,7 +413,8 @@ var TimelinePanel = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* scroll to show the read-up-to marker
|
/* scroll to show the read-up-to marker. We put it 1/3 of the way down
|
||||||
|
* the container.
|
||||||
*/
|
*/
|
||||||
jumpToReadMarker: function() {
|
jumpToReadMarker: function() {
|
||||||
if (!this.refs.messagePanel)
|
if (!this.refs.messagePanel)
|
||||||
@ -432,13 +433,14 @@ var TimelinePanel = React.createClass({
|
|||||||
if (ret !== null) {
|
if (ret !== null) {
|
||||||
// The messagepanel knows where the RM is, so we must have loaded
|
// The messagepanel knows where the RM is, so we must have loaded
|
||||||
// the relevant event.
|
// the relevant event.
|
||||||
this.refs.messagePanel.scrollToEvent(this.state.readMarkerEventId);
|
this.refs.messagePanel.scrollToEvent(this.state.readMarkerEventId,
|
||||||
|
0, 1/3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Looks like we haven't loaded the event corresponding to the read-marker.
|
// Looks like we haven't loaded the event corresponding to the read-marker.
|
||||||
// As with jumpToLiveTimeline, we want to reload the timeline around the
|
// As with jumpToLiveTimeline, we want to reload the timeline around the
|
||||||
// read-marker.
|
// read-marker.
|
||||||
this._loadTimeline(this.state.readMarkerEventId);
|
this._loadTimeline(this.state.readMarkerEventId, 0, 1/3);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -518,7 +520,15 @@ var TimelinePanel = React.createClass({
|
|||||||
_initTimeline: function(props) {
|
_initTimeline: function(props) {
|
||||||
var initialEvent = props.eventId;
|
var initialEvent = props.eventId;
|
||||||
var pixelOffset = props.eventPixelOffset;
|
var pixelOffset = props.eventPixelOffset;
|
||||||
return this._loadTimeline(initialEvent, pixelOffset);
|
|
||||||
|
// if a pixelOffset is given, it is relative to the bottom of the
|
||||||
|
// container. If not, put the event in the middle of the container.
|
||||||
|
var offsetBase = 1;
|
||||||
|
if (pixelOffset == null) {
|
||||||
|
offsetBase = 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._loadTimeline(initialEvent, pixelOffset, offsetBase);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -529,12 +539,15 @@ var TimelinePanel = React.createClass({
|
|||||||
* scroll to the bottom of the room.
|
* scroll to the bottom of the room.
|
||||||
*
|
*
|
||||||
* @param {number?} pixelOffset offset to position the given event at
|
* @param {number?} pixelOffset offset to position the given event at
|
||||||
* (pixels from the bottom of the view). If undefined, will put the
|
* (pixels from the offsetBase). If omitted, defaults to 0.
|
||||||
* event 1/3 of the way down the view.
|
*
|
||||||
|
* @param {number?} offsetBase the reference point for the pixelOffset. 0
|
||||||
|
* means the top of the container, 1 means the bottom, and fractional
|
||||||
|
* values mean somewhere in the middle. If omitted, it defaults to 0.
|
||||||
*
|
*
|
||||||
* returns a promise which will resolve when the load completes.
|
* returns a promise which will resolve when the load completes.
|
||||||
*/
|
*/
|
||||||
_loadTimeline: function(eventId, pixelOffset) {
|
_loadTimeline: function(eventId, pixelOffset, offsetBase) {
|
||||||
this._timelineWindow = new Matrix.TimelineWindow(
|
this._timelineWindow = new Matrix.TimelineWindow(
|
||||||
MatrixClientPeg.get(), this.props.room,
|
MatrixClientPeg.get(), this.props.room,
|
||||||
{windowLimit: TIMELINE_CAP});
|
{windowLimit: TIMELINE_CAP});
|
||||||
@ -567,7 +580,8 @@ var TimelinePanel = React.createClass({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
this.refs.messagePanel.scrollToEvent(eventId, pixelOffset);
|
this.refs.messagePanel.scrollToEvent(eventId, pixelOffset,
|
||||||
|
offsetBase);
|
||||||
} else {
|
} else {
|
||||||
this.refs.messagePanel.scrollToBottom();
|
this.refs.messagePanel.scrollToBottom();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user