mirror of
				https://github.com/vector-im/element-web.git
				synced 2025-11-04 02:02:14 +01:00 
			
		
		
		
	Move read-marker past our own events when we switch to a room
This fixes an issue where the RM appeared before any events which were pending when you switched away from that room (https://github.com/vector-im/vector-web/issues/1241). Also, fix a buglet in the MessagePanel which meant we didn't animate the disappearance of a RM when it stayed at the same event but became invisible. This didn't really cause any user-visible problems (because typically we advance the RM at the same time as it became invisible), but confused me a bit while I was trying to debug this.
This commit is contained in:
		
							parent
							
								
									c1101d978e
								
							
						
					
					
						commit
						3736fcf80e
					
				@ -173,15 +173,29 @@ module.exports = React.createClass({
 | 
				
			|||||||
        // first figure out which is the last event in the list which we're
 | 
					        // first figure out which is the last event in the list which we're
 | 
				
			||||||
        // actually going to show; this allows us to behave slightly
 | 
					        // actually going to show; this allows us to behave slightly
 | 
				
			||||||
        // differently for the last event in the list.
 | 
					        // differently for the last event in the list.
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // we also need to figure out which is the last event we show which isn't
 | 
				
			||||||
 | 
					        // a local echo, to manage the read-marker.
 | 
				
			||||||
 | 
					        var lastShownEventIndex = -1;
 | 
				
			||||||
 | 
					        var lastShownNonLocalEchoIndex = -1;
 | 
				
			||||||
        for (i = this.props.events.length-1; i >= 0; i--) {
 | 
					        for (i = this.props.events.length-1; i >= 0; i--) {
 | 
				
			||||||
            var mxEv = this.props.events[i];
 | 
					            var mxEv = this.props.events[i];
 | 
				
			||||||
            if (!EventTile.haveTileForEvent(mxEv)) {
 | 
					            if (!EventTile.haveTileForEvent(mxEv)) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (lastShownEventIndex < 0) {
 | 
				
			||||||
 | 
					                lastShownEventIndex = i;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (mxEv.status) {
 | 
				
			||||||
 | 
					                // this is a local echo
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            lastShownNonLocalEchoIndex = i;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var lastShownEventIndex = i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var ret = [];
 | 
					        var ret = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -213,25 +227,34 @@ module.exports = React.createClass({
 | 
				
			|||||||
                ret.push(<li key={eventId} data-scroll-token={eventId}/>);
 | 
					                ret.push(<li key={eventId} data-scroll-token={eventId}/>);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var isVisibleReadMarker = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (eventId == this.props.readMarkerEventId) {
 | 
					            if (eventId == this.props.readMarkerEventId) {
 | 
				
			||||||
                var visible = this.props.readMarkerVisible;
 | 
					                var visible = this.props.readMarkerVisible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // if the read marker comes at the end of the timeline, we don't want
 | 
					                // if the read marker comes at the end of the timeline (except
 | 
				
			||||||
                // to show it, but we still want to create the <li/> for it so that the
 | 
					                // for local echoes, which are excluded from RMs, because they
 | 
				
			||||||
                // algorithms which depend on its position on the screen aren't confused.
 | 
					                // don't have useful event ids), we don't want to show it, but
 | 
				
			||||||
                if (i >= lastShownEventIndex) {
 | 
					                // we still want to create the <li/> for it so that the
 | 
				
			||||||
 | 
					                // algorithms which depend on its position on the screen aren't
 | 
				
			||||||
 | 
					                // confused.
 | 
				
			||||||
 | 
					                if (i >= lastShownNonLocalEchoIndex) {
 | 
				
			||||||
                    visible = false;
 | 
					                    visible = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                ret.push(this._getReadMarkerTile(visible));
 | 
					                ret.push(this._getReadMarkerTile(visible));
 | 
				
			||||||
                readMarkerVisible = visible;
 | 
					                readMarkerVisible = visible;
 | 
				
			||||||
            } else if (eventId == this.currentReadMarkerEventId && !this.currentGhostEventId) {
 | 
					                isVisibleReadMarker = visible;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (eventId == this.currentGhostEventId) {
 | 
				
			||||||
 | 
					                // if we're showing an animation, continue to show it.
 | 
				
			||||||
 | 
					                ret.push(this._getReadMarkerGhostTile());
 | 
				
			||||||
 | 
					            } else if (!isVisibleReadMarker &&
 | 
				
			||||||
 | 
					                       eventId == this.currentReadMarkerEventId) {
 | 
				
			||||||
                // there is currently a read-up-to marker at this point, but no
 | 
					                // there is currently a read-up-to marker at this point, but no
 | 
				
			||||||
                // more. Show an animation of it disappearing.
 | 
					                // more. Show an animation of it disappearing.
 | 
				
			||||||
                ret.push(this._getReadMarkerGhostTile());
 | 
					                ret.push(this._getReadMarkerGhostTile());
 | 
				
			||||||
                this.currentGhostEventId = eventId;
 | 
					                this.currentGhostEventId = eventId;
 | 
				
			||||||
            } else if (eventId == this.currentGhostEventId) {
 | 
					 | 
				
			||||||
                // if we're showing an animation, continue to show it.
 | 
					 | 
				
			||||||
                ret.push(this._getReadMarkerGhostTile());
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -360,8 +360,6 @@ var TimelinePanel = React.createClass({
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var currentIndex = this._indexForEventId(this.state.readMarkerEventId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // move the RM to *after* the message at the bottom of the screen. This
 | 
					        // move the RM to *after* the message at the bottom of the screen. This
 | 
				
			||||||
        // avoids a problem whereby we never advance the RM if there is a huge
 | 
					        // avoids a problem whereby we never advance the RM if there is a huge
 | 
				
			||||||
        // message which doesn't fit on the screen.
 | 
					        // message which doesn't fit on the screen.
 | 
				
			||||||
@ -392,6 +390,38 @@ var TimelinePanel = React.createClass({
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // advance the read marker past any events we sent ourselves.
 | 
				
			||||||
 | 
					    _advanceReadMarkerPastMyEvents: function() {
 | 
				
			||||||
 | 
					        // we call _timelineWindow.getEvents() rather than using
 | 
				
			||||||
 | 
					        // this.state.events, because react batches the update to the latter, so it
 | 
				
			||||||
 | 
					        // may not have been updated yet.
 | 
				
			||||||
 | 
					        var events = this._timelineWindow.getEvents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // first find where the current RM is
 | 
				
			||||||
 | 
					        for (var i = 0; i < events.length; i++) {
 | 
				
			||||||
 | 
					            if (events[i].getId() == this.state.readMarkerEventId)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (i >= events.length) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // now think about advancing it
 | 
				
			||||||
 | 
					        var myUserId = MatrixClientPeg.get().credentials.userId;
 | 
				
			||||||
 | 
					        for (; i < events.length; i++) {
 | 
				
			||||||
 | 
					            var ev = events[i];
 | 
				
			||||||
 | 
					            if (!ev.sender || ev.sender.userId != myUserId) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // i is now the first unread message which we didn't send ourselves.
 | 
				
			||||||
 | 
					        i--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var ev = events[i];
 | 
				
			||||||
 | 
					        this._setReadMarker(ev.getId(), ev.getTs());
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* jump down to the bottom of this room, where new events are arriving
 | 
					    /* jump down to the bottom of this room, where new events are arriving
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    jumpToLiveTimeline: function() {
 | 
					    jumpToLiveTimeline: function() {
 | 
				
			||||||
@ -544,6 +574,11 @@ var TimelinePanel = React.createClass({
 | 
				
			|||||||
        var onLoaded = () => {
 | 
					        var onLoaded = () => {
 | 
				
			||||||
            this._reloadEvents();
 | 
					            this._reloadEvents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // If we switched away from the room while there were pending
 | 
				
			||||||
 | 
					            // outgoing events, the read-marker will be before those events.
 | 
				
			||||||
 | 
					            // We need to skip over any which have subsequently been sent.
 | 
				
			||||||
 | 
					            this._advanceReadMarkerPastMyEvents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.setState({timelineLoading: false}, () => {
 | 
					            this.setState({timelineLoading: false}, () => {
 | 
				
			||||||
                // initialise the scroll state of the message panel
 | 
					                // initialise the scroll state of the message panel
 | 
				
			||||||
                if (!this.refs.messagePanel) {
 | 
					                if (!this.refs.messagePanel) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user