Merge commit 'eb91faf' into rav/roomview_works

Conflicts:
	src/components/structures/RoomView.js
This commit is contained in:
Richard van der Hoff 2016-02-23 12:56:54 +00:00
commit 4c571cf1bf
3 changed files with 60 additions and 56 deletions

View file

@ -129,25 +129,39 @@ module.exports = React.createClass({
this.eventNodes = {}; this.eventNodes = {};
// we do two passes over the events list; first of all, we figure out var i;
// which events we want to show, and where the read markers fit into
// the list; then we actually create the event tiles. This allows us to
// behave slightly differently for the last event in the list.
//
// (Arguably we could do this when the events are added to this.props,
// but that would make it trickier to keep in sync with the read marker, given
// the read marker isn't necessarily on an event which we will show).
//
var eventsToShow = [];
// the index in 'eventsToShow' of the event *before* which we put the // first figure out which is the last event in the list which we're
// read marker or its ghost. (Note that it may be equal to // actually going to show; this allows us to behave slightly
// eventsToShow.length, which means it would be at the end of the timeline) // differently for the last event in the list.
var ghostIndex, readMarkerIndex; for (i = this.props.events.length-1; i >= 0; i--) {
var mxEv = this.props.events[i];
if (!EventTile.haveTileForEvent(mxEv)) {
continue;
}
for (var i = 0; i < this.props.events.length; i++) { if (this.props.isConferenceUser && mxEv.getType() === "m.room.member") {
if (this.props.isConferenceUser(mxEv.getSender()) ||
this.props.isConferenceUser(mxEv.getStateKey())) {
continue; // suppress conf user join/parts
}
}
break;
}
var lastShownEventIndex = i;
var ret = [];
var prevEvent = null; // the last event we showed
// assume there is no read marker until proven otherwise
var readMarkerVisible = false;
for (i = 0; i < this.props.events.length; i++) {
var mxEv = this.props.events[i]; var mxEv = this.props.events[i];
var wantTile = true; var wantTile = true;
var eventId = mxEv.getId();
if (!EventTile.haveTileForEvent(mxEv)) { if (!EventTile.haveTileForEvent(mxEv)) {
wantTile = false; wantTile = false;
@ -160,58 +174,34 @@ module.exports = React.createClass({
} }
} }
var last = (i == lastShownEventIndex);
if (wantTile) { if (wantTile) {
eventsToShow.push(mxEv); ret.push(this._getTilesForEvent(prevEvent, mxEv, last));
} else if (!mxEv.status) {
// if we aren't showing the event, put in a dummy scroll token anyway, so
// that we can scroll to the right place.
ret.push(<li key={eventId} data-scroll-token={eventId}/>);
} }
var eventId = mxEv.getId(); if (eventId == this.props.readMarkerEventId && i < lastShownEventIndex) {
if (eventId == this.props.readMarkerEventId) {
readMarkerIndex = eventsToShow.length;
} else if (eventId == this.currentReadMarkerEventId && !this.currentGhostEventId) {
// there is currently a read-up-to marker at this point, but no
// more. Show an animation of it disappearing.
ghostIndex = eventsToShow.length;
this.currentGhostEventId = eventId;
} else if (eventId == this.currentGhostEventId) {
// if we're showing an animation, continue to show it.
ghostIndex = eventsToShow.length;
}
}
var ret = [];
var prevEvent = null; // the last event we showed
// assume there is no read marker until proven otherwise
var readMarkerVisible = false;
for (var i = 0; i < eventsToShow.length; i++) {
var mxEv = eventsToShow[i];
var wantTile = true;
// insert the read marker if appropriate. Note that doing it here
// implicitly means that we never put it at the end of the timeline,
// because i will never reach eventsToShow.length.
if (i == readMarkerIndex) {
// suppress the read marker if the next event is sent by us; this // suppress the read marker if the next event is sent by us; this
// is a nonsensical and temporary situation caused by the delay between // is a nonsensical and temporary situation caused by the delay between
// us sending a message and receiving the synthesized receipt. // us sending a message and receiving the synthesized receipt.
if (mxEv.sender && mxEv.sender.userId != this.props.ourUserId) { var nextEvent = this.props.events[i+1];
if (nextEvent.sender && nextEvent.sender.userId != this.props.ourUserId) {
ret.push(this._getReadMarkerTile()); ret.push(this._getReadMarkerTile());
readMarkerVisible = true; readMarkerVisible = true;
} }
} else if (i == ghostIndex) { } else if (eventId == this.currentReadMarkerEventId && !this.currentGhostEventId) {
// there is currently a read-up-to marker at this point, but no
// more. Show an animation of it disappearing.
ret.push(this._getReadMarkerGhostTile());
this.currentGhostEventId = eventId;
} else if (eventId == this.currentGhostEventId) {
// if we're showing an animation, continue to show it.
ret.push(this._getReadMarkerGhostTile()); ret.push(this._getReadMarkerGhostTile());
} }
var last = false;
if (i == eventsToShow.length - 1) {
last = true;
}
// add the tiles for this event
ret.push(this._getTilesForEvent(prevEvent, mxEv, last));
prevEvent = mxEv;
} }
this.currentReadMarkerEventId = readMarkerVisible ? this.props.readMarkerEventId : null; this.currentReadMarkerEventId = readMarkerVisible ? this.props.readMarkerEventId : null;

View file

@ -92,6 +92,7 @@ module.exports = React.createClass({
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline); MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline);
MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt); MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt);
MatrixClientPeg.get().on("Room.redaction", this.onRoomRedaction);
this._initTimeline(this.props); this._initTimeline(this.props);
}, },
@ -121,6 +122,7 @@ module.exports = React.createClass({
if (client) { if (client) {
client.removeListener("Room.timeline", this.onRoomTimeline); client.removeListener("Room.timeline", this.onRoomTimeline);
client.removeListener("Room.receipt", this.onRoomReceipt); client.removeListener("Room.receipt", this.onRoomReceipt);
client.removeListener("Room.redaction", this.onRoomRedaction);
} }
}, },
@ -202,6 +204,17 @@ module.exports = React.createClass({
}); });
}, },
onRoomRedaction: function(ev, room) {
if (this.unmounted) return;
// ignore events for other rooms
if (room !== this.props.room) return;
// we could skip an update if the event isn't in our timeline,
// but that's probably an early optimisation.
this.forceUpdate();
},
sendReadReceipt: function() { sendReadReceipt: function() {
if (!this.refs.messagePanel) return; if (!this.refs.messagePanel) return;

View file

@ -65,6 +65,7 @@ module.exports = React.createClass({
statics: { statics: {
haveTileForEvent: function(e) { haveTileForEvent: function(e) {
if (e.isRedacted()) return false;
if (eventTileTypes[e.getType()] == undefined) return false; if (eventTileTypes[e.getType()] == undefined) return false;
if (eventTileTypes[e.getType()] == 'messages.TextualEvent') { if (eventTileTypes[e.getType()] == 'messages.TextualEvent') {
return TextForEvent.textForEvent(e) !== ''; return TextForEvent.textForEvent(e) !== '';