-
-
Notifications
You must be signed in to change notification settings - Fork 833
Conversation
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.
Put a XXX to indicate that the ghost tile should be replaced with something mor e stable. As it stands, the ghost will appear, potentially at a different position to the RMs actual position
@@ -388,6 +388,8 @@ module.exports = React.createClass({ | |||
isVisibleReadMarker = visible; | |||
} | |||
|
|||
// XXX: there should be no need for a ghost tile - we should just use a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you may be right that there is no need for a ghost tile, but I don't think the reason for its presence is to start the RM animation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I can see, the ghost tile is the one that animates and the ref
on the ghost is used to start the animation. This could be so much better. The non-ghost isn't even swapped out (as in there are states where both can be shown), so the client sometimes shows two markers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, but I don't understand why that means you don't need a ghost. It exists to hold the animation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could reuse the original marker and start the animation by calling Velocity
on it before it moves. Instead of using a ref
on the ghost, we'd use it on the original.
} else { | ||
initialReadMarker = this._getCurrentReadReceipt(); | ||
} | ||
console.info('Read marker initially', initialReadMarker); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not really
@@ -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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't forget to remove it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
&& 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
initialise this in componentWillMount
please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
}); | ||
console.log('TimelinePanel: Read marker sent to the server ', this.state.readMarkerEventId, ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this? looks spammy
@@ -706,7 +735,7 @@ var TimelinePanel = React.createClass({ | |||
|
|||
// the messagePanel doesn't know where the read marker is. | |||
// if we know the timestamp of the read marker, make a guess based on that. | |||
var rmTs = TimelinePanel.roomReadMarkerTsMap[this.props.timelineSet.roomId]; | |||
const rmTs = TimelinePanel.roomReadMarkerTsMap[this.props.timelineSet.room.roomId]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huh. Has this been broken for a while?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it! This is reached if MessagePanel
has not got the related event paginated in.
It doesn't look like much is done with the result of TimelinePanel.getReadMarkerPosition()
other than checking that it's in the view-port when updateReadMarker
is called (which might explain why we were seeing it following when scrolling down) and specifying whether it's visible to MessagePanel
.
@@ -414,9 +417,10 @@ var TimelinePanel = React.createClass({ | |||
} else if(lastEv && this.getReadMarkerPosition() === 0) { | |||
// we know we're stuckAtBottom, so we can advance the RM | |||
// immediately, to save a later render cycle | |||
|
|||
// This call will setState with readMarkerEventId = lastEv.getId() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... except that the true
argument is called inhibitSetState
- so I don't think it will.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah
if (ev.getType() !== "m.fully_read") return; | ||
|
||
const markerEventId = ev.getContent().event_id; | ||
console.log('TimelinePanel: Read marker received from server', markerEventId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this? looks spammy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true!
const markerEventId = ev.getContent().event_id; | ||
console.log('TimelinePanel: Read marker received from server', markerEventId); | ||
|
||
this.setState({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems like a problem that we aren't updating roomReadMarkerTsMap
here.
I suspect we actually no longer need roomReadMarkerTsMap, but if that's true, let's get rid of it (preferably in a separate PR) rather than leave it in an inconsistent state.
@@ -956,16 +985,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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment still looks valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair point!
This will become redundant when there is server support for directionality of the RM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
// 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won't this mean we hit the API every time the user moves the mouse? I feel like we should leave this set if sendReadReceipt
succeeds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If sendReadReceipt
is called, it'll return a promise this line is not reached.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, yes.
).catch(() => { | ||
).catch((e) => { | ||
// /read_markers API is not implemented on this HS, fallback to just RR | ||
if (e.errcode === 'M_UNRECOGNIZED') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what should be the behaviour for other errors? should we not set last_rr_sent_event_id = undefined
so that we retry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, yes I think that's the Right Way to do it
Indicate that setting the RR was a failure and that hitting the API should be retried (in the case where the errcode !== "M_UNRECOGNISED")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
This uses the new RM syncing API: