Merge pull request #2456 from matrix-org/bwindels/extendtypingbartiming
Avoid "jumpiness" with inline typing indicator
This commit is contained in:
commit
3c8bd3fc78
5 changed files with 154 additions and 11 deletions
|
@ -631,13 +631,29 @@ module.exports = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
_scrollDownIfAtBottom: function() {
|
||||
_onTypingVisible: function() {
|
||||
const scrollPanel = this.refs.scrollPanel;
|
||||
if (scrollPanel) {
|
||||
if (scrollPanel && scrollPanel.getScrollState().stuckAtBottom) {
|
||||
scrollPanel.blockShrinking();
|
||||
// scroll down if at bottom
|
||||
scrollPanel.checkScroll();
|
||||
}
|
||||
},
|
||||
|
||||
updateTimelineMinHeight: function() {
|
||||
const scrollPanel = this.refs.scrollPanel;
|
||||
const whoIsTyping = this.refs.whoIsTyping;
|
||||
const isTypingVisible = whoIsTyping && whoIsTyping.isVisible();
|
||||
|
||||
if (scrollPanel) {
|
||||
if (isTypingVisible) {
|
||||
scrollPanel.blockShrinking();
|
||||
} else {
|
||||
scrollPanel.clearBlockShrinking();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onResize: function() {
|
||||
dis.dispatch({ action: 'timeline_resize' }, true);
|
||||
},
|
||||
|
@ -666,7 +682,7 @@ module.exports = React.createClass({
|
|||
|
||||
let whoIsTyping;
|
||||
if (this.props.room) {
|
||||
whoIsTyping = (<WhoIsTypingTile room={this.props.room} onVisible={this._scrollDownIfAtBottom} />);
|
||||
whoIsTyping = (<WhoIsTypingTile room={this.props.room} onVisible={this._onTypingVisible} ref="whoIsTyping" />);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -223,6 +223,8 @@ module.exports = React.createClass({
|
|||
|
||||
onResize: function() {
|
||||
this.props.onResize();
|
||||
// clear min-height as the height might have changed
|
||||
this.clearBlockShrinking();
|
||||
this.checkScroll();
|
||||
if (this._gemScroll) this._gemScroll.forceUpdate();
|
||||
},
|
||||
|
@ -372,6 +374,8 @@ module.exports = React.createClass({
|
|||
}
|
||||
this._unfillDebouncer = setTimeout(() => {
|
||||
this._unfillDebouncer = null;
|
||||
// if timeline shrinks, min-height should be cleared
|
||||
this.clearBlockShrinking();
|
||||
this.props.onUnfillRequest(backwards, markerScrollToken);
|
||||
}, UNFILL_REQUEST_DEBOUNCE_MS);
|
||||
}
|
||||
|
@ -678,6 +682,29 @@ module.exports = React.createClass({
|
|||
this._gemScroll = gemScroll;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the current height as the min height for the message list
|
||||
* so the timeline cannot shrink. This is used to avoid
|
||||
* jumping when the typing indicator gets replaced by a smaller message.
|
||||
*/
|
||||
blockShrinking: function() {
|
||||
const messageList = this.refs.itemlist;
|
||||
if (messageList) {
|
||||
const currentHeight = messageList.clientHeight;
|
||||
messageList.style.minHeight = `${currentHeight}px`;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the previously set min height
|
||||
*/
|
||||
clearBlockShrinking: function() {
|
||||
const messageList = this.refs.itemlist;
|
||||
if (messageList) {
|
||||
messageList.style.minHeight = null;
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
|
||||
// TODO: the classnames on the div and ol could do with being updated to
|
||||
|
|
|
@ -455,7 +455,7 @@ var TimelinePanel = React.createClass({
|
|||
//
|
||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
const sender = ev.sender ? ev.sender.userId : null;
|
||||
var callback = null;
|
||||
var callRMUpdated = false;
|
||||
if (sender != myUserId && !UserActivity.userCurrentlyActive()) {
|
||||
updatedState.readMarkerVisible = true;
|
||||
} else if (lastEv && this.getReadMarkerPosition() === 0) {
|
||||
|
@ -465,11 +465,16 @@ var TimelinePanel = React.createClass({
|
|||
this._setReadMarker(lastEv.getId(), lastEv.getTs(), true);
|
||||
updatedState.readMarkerVisible = false;
|
||||
updatedState.readMarkerEventId = lastEv.getId();
|
||||
callback = this.props.onReadMarkerUpdated;
|
||||
callRMUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState(updatedState, callback);
|
||||
this.setState(updatedState, () => {
|
||||
this.refs.messagePanel.updateTimelineMinHeight();
|
||||
if (callRMUpdated) {
|
||||
this.props.onReadMarkerUpdated();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue