Only show read marker if it's somewhere other than at the bottom, make it animate away and put a short delay before the read marker advances so quickly changing to a room and then away again doesn't advance your read marker.
This commit is contained in:
parent
b37ea52a1f
commit
d63f83187f
1 changed files with 70 additions and 6 deletions
|
@ -40,6 +40,7 @@ var dis = require("../../dispatcher");
|
||||||
|
|
||||||
var PAGINATE_SIZE = 20;
|
var PAGINATE_SIZE = 20;
|
||||||
var INITIAL_SIZE = 20;
|
var INITIAL_SIZE = 20;
|
||||||
|
var SEND_READ_RECEIPT_DELAY = 2000;
|
||||||
|
|
||||||
var DEBUG_SCROLL = false;
|
var DEBUG_SCROLL = false;
|
||||||
|
|
||||||
|
@ -74,6 +75,8 @@ module.exports = React.createClass({
|
||||||
syncState: MatrixClientPeg.get().getSyncState(),
|
syncState: MatrixClientPeg.get().getSyncState(),
|
||||||
hasUnsentMessages: this._hasUnsentMessages(room),
|
hasUnsentMessages: this._hasUnsentMessages(room),
|
||||||
callState: null,
|
callState: null,
|
||||||
|
readReceiptEventId: room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId),
|
||||||
|
readMarkerGhostEventId: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -100,6 +103,12 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
// if we're waiting to send a read receipt, don't:
|
||||||
|
// message wasn't on screen for long enough
|
||||||
|
if (this.sendRRTimer) {
|
||||||
|
clearTimeout(this.sendRRTimer);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.refs.messagePanel) {
|
if (this.refs.messagePanel) {
|
||||||
// disconnect the D&D event listeners from the message panel. This
|
// disconnect the D&D event listeners from the message panel. This
|
||||||
// is really just for hygiene - the messagePanel is going to be
|
// is really just for hygiene - the messagePanel is going to be
|
||||||
|
@ -237,7 +246,16 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
onRoomReceipt: function(receiptEvent, room) {
|
onRoomReceipt: function(receiptEvent, room) {
|
||||||
if (room.roomId == this.props.roomId) {
|
if (room.roomId == this.props.roomId) {
|
||||||
this.forceUpdate();
|
var readReceiptEventId = this.state.room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId);
|
||||||
|
var readMarkerGhostEventId = this.state.readMarkerGhostEventId;
|
||||||
|
if (this.state.readReceiptEventId !== undefined && this.state.readReceiptEventId != readReceiptEventId) {
|
||||||
|
var newReadEventIndex = this._indexForEventId(readReceiptEventId);
|
||||||
|
readMarkerGhostEventId = this.state.readReceiptEventId;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
readReceiptEventId: readReceiptEventId,
|
||||||
|
readMarkerGhostEventId: readMarkerGhostEventId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -649,10 +667,10 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
var EventTile = sdk.getComponent('rooms.EventTile');
|
var EventTile = sdk.getComponent('rooms.EventTile');
|
||||||
|
|
||||||
|
|
||||||
var prevEvent = null; // the last event we showed
|
var prevEvent = null; // the last event we showed
|
||||||
var readReceiptEventId = this.state.room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId);
|
|
||||||
var startIdx = Math.max(0, this.state.room.timeline.length - this.state.messageCap);
|
var startIdx = Math.max(0, this.state.room.timeline.length - this.state.messageCap);
|
||||||
|
var readMarkerIndex;
|
||||||
|
var ghostIndex;
|
||||||
for (var i = startIdx; i < this.state.room.timeline.length; i++) {
|
for (var i = startIdx; i < this.state.room.timeline.length; i++) {
|
||||||
var mxEv = this.state.room.timeline[i];
|
var mxEv = this.state.room.timeline[i];
|
||||||
|
|
||||||
|
@ -666,6 +684,24 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now we've decided whether or not to show this messages,
|
||||||
|
// add the read up to marker if appropriate
|
||||||
|
// doing this here means we implicitly do not show the marker
|
||||||
|
// if it's at the bottom
|
||||||
|
// NB. it would be better to decide where the read marker was going
|
||||||
|
// when the state changed rather than here in the render method, but
|
||||||
|
// this is where we decide what messages we show so it's the only
|
||||||
|
// place we know whether we're at the bottom or not.
|
||||||
|
var self = this;
|
||||||
|
if (prevEvent && prevEvent.getId() == this.state.readReceiptEventId) {
|
||||||
|
var hr;
|
||||||
|
hr = (<hr className="mx_RoomView_myReadMarker" style={{opacity: 1, width: '85%'}} ref={function(n) {
|
||||||
|
self.readMarkerNode = n;
|
||||||
|
}} />);
|
||||||
|
readMarkerIndex = ret.length;
|
||||||
|
ret.push(<li key="_readupto" className="mx_RoomView_myReadMarker_container">{hr}</li>);
|
||||||
|
}
|
||||||
|
|
||||||
// is this a continuation of the previous message?
|
// is this a continuation of the previous message?
|
||||||
var continuation = false;
|
var continuation = false;
|
||||||
if (prevEvent !== null) {
|
if (prevEvent !== null) {
|
||||||
|
@ -702,13 +738,29 @@ module.exports = React.createClass({
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (eventId == readReceiptEventId) {
|
// A read up to marker has died and returned as a ghost!
|
||||||
ret.push(<hr className="mx_RoomView_myReadMarker" />);
|
// Lives in the dom as the ghost of the previous one while it fades away
|
||||||
|
if (eventId == this.state.readMarkerGhostEventId) {
|
||||||
|
ghostIndex = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
prevEvent = mxEv;
|
prevEvent = mxEv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// splice the read marker ghost in now that we know whether the read receipt
|
||||||
|
// is the last element or not, because we only decide as we're going along.
|
||||||
|
if (readMarkerIndex === undefined && ghostIndex && ghostIndex <= ret.length) {
|
||||||
|
var hr;
|
||||||
|
hr = (<hr className="mx_RoomView_myReadMarker" style={{opacity: 1, width: '85%'}} ref={function(n) {
|
||||||
|
Velocity(n, {opacity: '0', width: '10%'}, {duration: 400, complete: function() {
|
||||||
|
self.setState({readMarkerGhostEventId: undefined});
|
||||||
|
}});
|
||||||
|
}} />);
|
||||||
|
ret.splice(ghostIndex, 0, (
|
||||||
|
<li key="_readuptoghost" className="mx_RoomView_myReadMarker_container">{hr}</li>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -815,6 +867,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
sendReadReceipt: function() {
|
sendReadReceipt: function() {
|
||||||
if (!this.state.room) return;
|
if (!this.state.room) return;
|
||||||
|
|
||||||
var currentReadUpToEventId = this.state.room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId);
|
var currentReadUpToEventId = this.state.room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId);
|
||||||
var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId);
|
var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId);
|
||||||
|
|
||||||
|
@ -822,7 +875,18 @@ module.exports = React.createClass({
|
||||||
if (lastReadEventIndex === null) return;
|
if (lastReadEventIndex === null) return;
|
||||||
|
|
||||||
if (lastReadEventIndex > currentReadUpToEventIndex) {
|
if (lastReadEventIndex > currentReadUpToEventIndex) {
|
||||||
MatrixClientPeg.get().sendReadReceipt(this.state.room.timeline[lastReadEventIndex]);
|
var self = this;
|
||||||
|
|
||||||
|
var lastReadEventId = self.state.room.timeline[lastReadEventIndex].getId();
|
||||||
|
if (this.pendingRR != lastReadEventId) {
|
||||||
|
this.pendingRR = lastReadEventId;
|
||||||
|
if (this.sendRRTimer) clearTimeout(this.sendRRTimer);
|
||||||
|
this.sendRRTimer = setTimeout(function() {
|
||||||
|
MatrixClientPeg.get().sendReadReceipt(self.state.room.timeline[lastReadEventIndex]);
|
||||||
|
self.sendRRTimer = undefined;
|
||||||
|
self.pendingRR = undefined;
|
||||||
|
}, SEND_READ_RECEIPT_DELAY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue