Initial implementation of using new RM API
As detailed here https://docs.google.com/document/d/1UWqdS-e1sdwkLDUY0wA4gZyIkRp-ekjsLZ8k6g_Zvso/edit, the RM state is no longer kept locally, but rather server-side. The client now uses it's locally-calculated RM to update the server and receives server updates via the per-room account data. The sending of the RR has been bundled in to reduce traffic when sending both. In effect, whenever a RR is sent the RM is sent with it but using the new API. This uses a js-sdk change which has set to be finalised and so might change.pull/21833/head
							parent
							
								
									424aae6b91
								
							
						
					
					
						commit
						1c25ed89b0
					
				| 
						 | 
				
			
			@ -102,9 +102,6 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    statics: {
 | 
			
		||||
        // a map from room id to read marker event ID
 | 
			
		||||
        roomReadMarkerMap: {},
 | 
			
		||||
 | 
			
		||||
        // a map from room id to read marker event timestamp
 | 
			
		||||
        roomReadMarkerTsMap: {},
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -121,10 +118,15 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
    getInitialState: function() {
 | 
			
		||||
        // XXX: we could track RM per TimelineSet rather than per Room.
 | 
			
		||||
        // but for now we just do it per room for simplicity.
 | 
			
		||||
        let initialReadMarker = null;
 | 
			
		||||
        if (this.props.manageReadMarkers) {
 | 
			
		||||
            var initialReadMarker =
 | 
			
		||||
                TimelinePanel.roomReadMarkerMap[this.props.timelineSet.room.roomId]
 | 
			
		||||
                           || this._getCurrentReadReceipt();
 | 
			
		||||
            const readmarker = this.props.timelineSet.room.getAccountData('m.read_marker');
 | 
			
		||||
            if (readmarker){
 | 
			
		||||
                initialReadMarker = readmarker.getContent().marker;
 | 
			
		||||
            } else {
 | 
			
		||||
                initialReadMarker = this._getCurrentReadReceipt();
 | 
			
		||||
            }
 | 
			
		||||
            console.info('Read marker initially', initialReadMarker);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +182,7 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
        MatrixClientPeg.get().on("Room.redaction", this.onRoomRedaction);
 | 
			
		||||
        MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
 | 
			
		||||
        MatrixClientPeg.get().on("Room.localEchoUpdated", this.onLocalEchoUpdated);
 | 
			
		||||
        MatrixClientPeg.get().on("Room.accountData", this.onAccountData);
 | 
			
		||||
 | 
			
		||||
        this._initTimeline(this.props);
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -466,6 +469,21 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
        this._reloadEvents();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onAccountData: function(ev, room) {
 | 
			
		||||
        if (this.unmounted) return;
 | 
			
		||||
 | 
			
		||||
        // ignore events for other rooms
 | 
			
		||||
        if (room !== this.props.timelineSet.room) return;
 | 
			
		||||
 | 
			
		||||
        if (ev.getType() !== "m.read_marker") return;
 | 
			
		||||
 | 
			
		||||
        const markerEventId = ev.getContent().marker;
 | 
			
		||||
        console.log('TimelinePanel: Read marker received from server', markerEventId);
 | 
			
		||||
 | 
			
		||||
        this.setState({
 | 
			
		||||
            readMarkerEventId: markerEventId,
 | 
			
		||||
        }, this.props.onReadMarkerUpdated);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    sendReadReceipt: function() {
 | 
			
		||||
        if (!this.refs.messagePanel) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -505,13 +523,23 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
 | 
			
		||||
        // we also remember the last read receipt we sent to avoid spamming the
 | 
			
		||||
        // same one at the server repeatedly
 | 
			
		||||
        if (lastReadEventIndex > currentReadUpToEventIndex
 | 
			
		||||
                && this.last_rr_sent_event_id != lastReadEvent.getId()) {
 | 
			
		||||
        if ((lastReadEventIndex > currentReadUpToEventIndex &&
 | 
			
		||||
            this.last_rr_sent_event_id != lastReadEvent.getId()) ||
 | 
			
		||||
                this.last_rm_sent_event_id != this.state.readMarkerEventId) {
 | 
			
		||||
 | 
			
		||||
            this.last_rr_sent_event_id = lastReadEvent.getId();
 | 
			
		||||
            MatrixClientPeg.get().sendReadReceipt(lastReadEvent).catch(() => {
 | 
			
		||||
            this.last_rm_sent_event_id = this.state.readMarkerEventId;
 | 
			
		||||
 | 
			
		||||
            MatrixClientPeg.get().setRoomReadMarker(
 | 
			
		||||
                this.props.timelineSet.room.roomId,
 | 
			
		||||
                this.state.readMarkerEventId,
 | 
			
		||||
                lastReadEvent
 | 
			
		||||
            ).catch(() => {
 | 
			
		||||
                // it failed, so allow retries next time the user is active
 | 
			
		||||
                this.last_rr_sent_event_id = undefined;
 | 
			
		||||
                this.last_rm_sent_event_id = undefined;
 | 
			
		||||
            });
 | 
			
		||||
            console.log('TimelinePanel: Read marker sent to the server ', this.state.readMarkerEventId, );
 | 
			
		||||
 | 
			
		||||
            // do a quick-reset of our unreadNotificationCount to avoid having
 | 
			
		||||
            // to wait from the remote echo from the homeserver.
 | 
			
		||||
| 
						 | 
				
			
			@ -956,16 +984,10 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
    _setReadMarker: function(eventId, eventTs, inhibitSetState) {
 | 
			
		||||
        var roomId = this.props.timelineSet.room.roomId;
 | 
			
		||||
 | 
			
		||||
        if (TimelinePanel.roomReadMarkerMap[roomId] == eventId) {
 | 
			
		||||
            // don't update the state (and cause a re-render) if there is
 | 
			
		||||
            // no change to the RM.
 | 
			
		||||
        if (eventId === this.state.readMarkerEventId) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // ideally we'd sync these via the server, but for now just stash them
 | 
			
		||||
        // in a map.
 | 
			
		||||
        TimelinePanel.roomReadMarkerMap[roomId] = eventId;
 | 
			
		||||
 | 
			
		||||
        // in order to later figure out if the read marker is
 | 
			
		||||
        // above or below the visible timeline, we stash the timestamp.
 | 
			
		||||
        TimelinePanel.roomReadMarkerTsMap[roomId] = eventTs;
 | 
			
		||||
| 
						 | 
				
			
			@ -974,6 +996,7 @@ var TimelinePanel = React.createClass({
 | 
			
		|||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Do the local echo of the RM
 | 
			
		||||
        // run the render cycle before calling the callback, so that
 | 
			
		||||
        // getReadMarkerPosition() returns the right thing.
 | 
			
		||||
        this.setState({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue