diff --git a/skins/base/views/organisms/RoomView.js b/skins/base/views/organisms/RoomView.js
index c8a943ee..4476ac8a 100644
--- a/skins/base/views/organisms/RoomView.js
+++ b/skins/base/views/organisms/RoomView.js
@@ -21,6 +21,7 @@ var React = require('react');
var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
var ComponentBroker = require('../../../../src/ComponentBroker');
+var classNames = require("classnames");
var MessageTile = ComponentBroker.get('molecules/MessageTile');
var RoomHeader = ComponentBroker.get('molecules/RoomHeader');
@@ -68,11 +69,17 @@ module.exports = React.createClass({
);
}
} else {
+ var scrollheader_classes = classNames({
+ mx_RoomView_scrollheader: true,
+ loading: this.state.paginating
+ });
return (
-
+
+ -
+
{this.getMessageTiles()}
diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js
index 4856e39a..cfe4dfd0 100644
--- a/src/controllers/organisms/RoomView.js
+++ b/src/controllers/organisms/RoomView.js
@@ -18,6 +18,8 @@ limitations under the License.
var MatrixClientPeg = require("../../MatrixClientPeg");
+var PAGINATE_SIZE = 20;
+
module.exports = {
getInitialState: function() {
return {
@@ -43,6 +45,12 @@ module.exports = {
},*/
onRoomTimeline: function(ev, room, toStartOfTimeline) {
+ // ignore anything that comes in whilst pagingating: we get one
+ // event for each new matrix event so this would cause a huge
+ // number of UI updates. Just update the UI when the paginate
+ // call returns.
+ if (this.state.paginating) return;
+
// no point handling anything while we're waiting for the join to finish:
// we'll only be showing a spinner.
if (this.state.joining) return;
@@ -55,22 +63,59 @@ module.exports = {
this.setState({
room: MatrixClientPeg.get().getRoom(this.props.roomId)
});
+
+ if (toStartOfTimeline && !this.state.paginating) {
+ this.fillSpace();
+ }
},
componentDidMount: function() {
if (this.refs.messageList) {
var messageUl = this.refs.messageList.getDOMNode();
messageUl.scrollTop = messageUl.scrollHeight;
+
+ this.fillSpace();
}
},
componentDidUpdate: function() {
- if (this.refs.messageList && this.atBottom) {
- var messageUl = this.refs.messageList.getDOMNode();
+ if (!this.refs.messageList) return;
+
+ var messageUl = this.refs.messageList.getDOMNode();
+
+ if (this.state.paginating && !this.waiting_for_paginate) {
+ var heightGained = messageUl.scrollHeight - this.oldScrollHeight;
+ messageUl.scrollTop += heightGained;
+ this.oldScrollHeight = undefined;
+ if (!this.fillSpace()) {
+ this.setState({paginating: false});
+ }
+ } else if (this.atBottom) {
messageUl.scrollTop = messageUl.scrollHeight;
}
},
+ fillSpace: function() {
+ var messageUl = this.refs.messageList.getDOMNode();
+ if (messageUl.scrollTop < messageUl.clientHeight) {
+ this.setState({paginating: true});
+ this.waiting_for_paginate = true;
+
+ this.oldScrollHeight = messageUl.scrollHeight;
+
+ var that = this;
+ MatrixClientPeg.get().scrollback(this.state.room, PAGINATE_SIZE).finally(function() {
+ that.waiting_for_paginate = false;
+ that.setState({
+ room: MatrixClientPeg.get().getRoom(that.props.roomId)
+ });
+ // wait and set paginating to false when the component updates
+ });
+ return true;
+ }
+ return false;
+ },
+
onJoinButtonClicked: function(ev) {
var that = this;
MatrixClientPeg.get().joinRoom(this.props.roomId).then(function() {
@@ -87,6 +132,14 @@ module.exports = {
this.setState({
joining: true
});
+ },
+
+ onMessageListScroll: function(ev) {
+ if (this.refs.messageList) {
+ var messageUl = this.refs.messageList.getDOMNode();
+ this.atBottom = messageUl.scrollHeight - messageUl.scrollTop <= messageUl.clientHeight;
+ }
+ if (!this.state.paginating) this.fillSpace();
}
};