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.
This commit is contained in:
parent
424aae6b91
commit
1c25ed89b0
1 changed files with 39 additions and 16 deletions
|
@ -102,9 +102,6 @@ var TimelinePanel = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
statics: {
|
statics: {
|
||||||
// a map from room id to read marker event ID
|
|
||||||
roomReadMarkerMap: {},
|
|
||||||
|
|
||||||
// a map from room id to read marker event timestamp
|
// a map from room id to read marker event timestamp
|
||||||
roomReadMarkerTsMap: {},
|
roomReadMarkerTsMap: {},
|
||||||
},
|
},
|
||||||
|
@ -121,10 +118,15 @@ var TimelinePanel = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
// XXX: we could track RM per TimelineSet rather than per Room.
|
// XXX: we could track RM per TimelineSet rather than per Room.
|
||||||
// but for now we just do it per room for simplicity.
|
// but for now we just do it per room for simplicity.
|
||||||
|
let initialReadMarker = null;
|
||||||
if (this.props.manageReadMarkers) {
|
if (this.props.manageReadMarkers) {
|
||||||
var initialReadMarker =
|
const readmarker = this.props.timelineSet.room.getAccountData('m.read_marker');
|
||||||
TimelinePanel.roomReadMarkerMap[this.props.timelineSet.room.roomId]
|
if (readmarker){
|
||||||
|| this._getCurrentReadReceipt();
|
initialReadMarker = readmarker.getContent().marker;
|
||||||
|
} else {
|
||||||
|
initialReadMarker = this._getCurrentReadReceipt();
|
||||||
|
}
|
||||||
|
console.info('Read marker initially', initialReadMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -180,6 +182,7 @@ var TimelinePanel = React.createClass({
|
||||||
MatrixClientPeg.get().on("Room.redaction", this.onRoomRedaction);
|
MatrixClientPeg.get().on("Room.redaction", this.onRoomRedaction);
|
||||||
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
|
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
|
||||||
MatrixClientPeg.get().on("Room.localEchoUpdated", this.onLocalEchoUpdated);
|
MatrixClientPeg.get().on("Room.localEchoUpdated", this.onLocalEchoUpdated);
|
||||||
|
MatrixClientPeg.get().on("Room.accountData", this.onAccountData);
|
||||||
|
|
||||||
this._initTimeline(this.props);
|
this._initTimeline(this.props);
|
||||||
},
|
},
|
||||||
|
@ -466,6 +469,21 @@ var TimelinePanel = React.createClass({
|
||||||
this._reloadEvents();
|
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() {
|
sendReadReceipt: function() {
|
||||||
if (!this.refs.messagePanel) return;
|
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
|
// we also remember the last read receipt we sent to avoid spamming the
|
||||||
// same one at the server repeatedly
|
// same one at the server repeatedly
|
||||||
if (lastReadEventIndex > currentReadUpToEventIndex
|
if ((lastReadEventIndex > currentReadUpToEventIndex &&
|
||||||
&& this.last_rr_sent_event_id != lastReadEvent.getId()) {
|
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();
|
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
|
// it failed, so allow retries next time the user is active
|
||||||
this.last_rr_sent_event_id = undefined;
|
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
|
// do a quick-reset of our unreadNotificationCount to avoid having
|
||||||
// to wait from the remote echo from the homeserver.
|
// to wait from the remote echo from the homeserver.
|
||||||
|
@ -956,16 +984,10 @@ var TimelinePanel = React.createClass({
|
||||||
_setReadMarker: function(eventId, eventTs, inhibitSetState) {
|
_setReadMarker: function(eventId, eventTs, inhibitSetState) {
|
||||||
var roomId = this.props.timelineSet.room.roomId;
|
var roomId = this.props.timelineSet.room.roomId;
|
||||||
|
|
||||||
if (TimelinePanel.roomReadMarkerMap[roomId] == eventId) {
|
if (eventId === this.state.readMarkerEventId) {
|
||||||
// don't update the state (and cause a re-render) if there is
|
|
||||||
// no change to the RM.
|
|
||||||
return;
|
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
|
// in order to later figure out if the read marker is
|
||||||
// above or below the visible timeline, we stash the timestamp.
|
// above or below the visible timeline, we stash the timestamp.
|
||||||
TimelinePanel.roomReadMarkerTsMap[roomId] = eventTs;
|
TimelinePanel.roomReadMarkerTsMap[roomId] = eventTs;
|
||||||
|
@ -974,6 +996,7 @@ var TimelinePanel = React.createClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do the local echo of the RM
|
||||||
// run the render cycle before calling the callback, so that
|
// run the render cycle before calling the callback, so that
|
||||||
// getReadMarkerPosition() returns the right thing.
|
// getReadMarkerPosition() returns the right thing.
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue