Remember to load new timeline events

Fixes a bug where we wouldn't load new timeline events if they arrived when we
were scrolled up (https://github.com/vector-im/vector-web/issues/1367)
pull/21833/head
Richard van der Hoff 2016-04-11 14:05:04 +01:00
parent 825e6702ef
commit e051d1528c
2 changed files with 88 additions and 0 deletions

View File

@ -264,6 +264,10 @@ var TimelinePanel = React.createClass({
// updates from pagination will happen when the paginate completes.
if (toStartOfTimeline || !data || !data.liveEvent) return;
// even if we previously gave up forward-paginating, it's worth
// having another go now.
this.setState({canForwardPaginate: true});
if (!this.refs.messagePanel) return;
if (!this.refs.messagePanel.getScrollState().stuckAtBottom) return;

View File

@ -40,6 +40,19 @@ describe('TimelinePanel', function() {
var timeline;
var parentDiv;
function mkMessage() {
return test_utils.mkMessage(
{
event: true, room: ROOM_ID, user: USER_ID,
ts: Date.now(),
});
}
function scryEventTiles(panel) {
return ReactTestUtils.scryRenderedComponentsWithType(
panel, sdk.getComponent('rooms.EventTile'));
};
beforeEach(function() {
test_utils.beforeEach(this);
sandbox = test_utils.stubClient(sandbox);
@ -69,6 +82,77 @@ describe('TimelinePanel', function() {
sandbox.restore();
});
it('should load new events even if you are scrolled up', function(done) {
// this is https://github.com/vector-im/vector-web/issues/1367
// enough events to allow us to scroll back
for (var i = 0; i < 40; i++) {
timeline.addEvent(mkMessage());
}
var scrollDefer;
var panel = ReactDOM.render(
<TimelinePanel room={room} onScroll={() => {scrollDefer.resolve()}}
/>,
parentDiv,
);
var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass(
panel, "gm-scroll-view");
// helper function which will return a promise which resolves when the
// panel isn't paginating
var awaitPaginationCompletion = function() {
if(!panel.state.forwardPaginating)
return q();
else
return q.delay(0).then(awaitPaginationCompletion);
};
// helper function which will return a promise which resolves when
// the TimelinePanel fires a scroll event
var awaitScroll = function() {
scrollDefer = q.defer();
return scrollDefer.promise;
};
// wait for the panel to load - we'll get a scroll event once it
// happens
awaitScroll().then(() => {
expect(panel.state.canBackPaginate).toBe(false);
expect(scryEventTiles(panel).length).toEqual(40);
// scroll up
console.log("setting scrollTop = 0");
scrollingDiv.scrollTop = 0;
// wait for the scroll event to land
}).then(awaitScroll).then(() => {
// there should be no pagination going on now
expect(panel.state.backPaginating).toBe(false);
expect(panel.state.forwardPaginating).toBe(false);
expect(panel.state.canBackPaginate).toBe(false);
expect(panel.state.canForwardPaginate).toBe(false);
expect(panel.isAtEndOfLiveTimeline()).toBe(false);
expect(scrollingDiv.scrollTop).toEqual(0);
console.log("adding event");
// a new event!
var ev = mkMessage();
timeline.addEvent(ev);
panel.onRoomTimeline(ev, room, false, false, {liveEvent: true});
// that won't make much difference, because we don't paginate
// unless we're at the bottom of the timeline, but a scroll event
// should be enough to set off a pagination.
expect(scryEventTiles(panel).length).toEqual(40);
scrollingDiv.scrollTop = 10;
}).delay(0).then(awaitPaginationCompletion).then(() => {
expect(scryEventTiles(panel).length).toEqual(41);
}).done(done);
});
it('should not paginate forever if there are no events', function(done) {
// start with a handful of events in the timeline, as would happen when
// joining a room