Merge commit 'eb91faf' into rav/roomview_works
Conflicts: src/components/structures/RoomView.js
This commit is contained in:
commit
4c571cf1bf
3 changed files with 60 additions and 56 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) !== '';
|
||||||
|
|
Loading…
Reference in a new issue