Skip to content

Commit 1dddcd4

Browse files
authored
Merge pull request #1663 from matrix-org/gsouquet-timeline-jumpiness
2 parents e277de6 + 2666a27 commit 1dddcd4

File tree

2 files changed

+49
-21
lines changed

2 files changed

+49
-21
lines changed

src/models/event.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export const MatrixEvent = function(
168168
/* The txnId with which this event was sent if it was during this session,
169169
allows for a unique ID which does not change when the event comes back down sync.
170170
*/
171-
this._txnId = null;
171+
this._txnId = event.txn_id || null;
172172

173173
/* Set an approximate timestamp for the event relative the local clock.
174174
* This will inherently be approximate because it doesn't take into account

src/models/room.js

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,13 @@ export function Room(roomId, client, myUserId, opts) {
194194
const serializedPendingEventList = client._sessionStore.store.getItem(pendingEventsKey(this.roomId));
195195
if (serializedPendingEventList) {
196196
JSON.parse(serializedPendingEventList)
197-
.forEach(serializedEvent => {
197+
.forEach(async serializedEvent => {
198198
const event = new MatrixEvent(serializedEvent);
199+
if (event.getType() === "m.room.encrypted") {
200+
await event.attemptDecryption(this._client._crypto);
201+
}
199202
event.setStatus(EventStatus.NOT_SENT);
200-
const txnId = client.makeTxnId();
201-
this.addPendingEvent(event, txnId);
203+
this.addPendingEvent(event, event.getTxnId());
202204
});
203205
}
204206
}
@@ -396,15 +398,7 @@ Room.prototype.removePendingEvent = function(eventId) {
396398
}, false,
397399
);
398400

399-
const { store } = this._client._sessionStore;
400-
if (this._pendingEventList.length > 0) {
401-
store.setItem(
402-
pendingEventsKey(this.roomId),
403-
JSON.stringify(this._pendingEventList),
404-
);
405-
} else {
406-
store.removeItem(pendingEventsKey(this.roomId));
407-
}
401+
this._savePendingEvents();
408402

409403
return removed;
410404
};
@@ -1271,11 +1265,7 @@ Room.prototype.addPendingEvent = function(event, txnId) {
12711265
event.setStatus(EventStatus.NOT_SENT);
12721266
}
12731267
this._pendingEventList.push(event);
1274-
const { store } = this._client._sessionStore;
1275-
store.setItem(
1276-
pendingEventsKey(this.roomId),
1277-
JSON.stringify(this._pendingEventList),
1278-
);
1268+
this._savePendingEvents();
12791269
if (event.isRelation()) {
12801270
// For pending events, add them to the relations collection immediately.
12811271
// (The alternate case below already covers this as part of adding to
@@ -1312,6 +1302,46 @@ Room.prototype.addPendingEvent = function(event, txnId) {
13121302

13131303
this.emit("Room.localEchoUpdated", event, this, null, null);
13141304
};
1305+
1306+
/**
1307+
* Persists all pending events to local storage
1308+
*
1309+
* If the current room is encrypted only encrypted events will be persisted
1310+
* all messages that are not yet encrypted will be discarded
1311+
*
1312+
* This is because the flow of EVENT_STATUS transition is
1313+
* queued => sending => encrypting => sending => sent
1314+
*
1315+
* Steps 3 and 4 are skipped for unencrypted room.
1316+
* It is better to discard an unencrypted message rather than persisting
1317+
* it locally for everyone to read
1318+
*/
1319+
Room.prototype._savePendingEvents = function() {
1320+
if (this._pendingEventList) {
1321+
const pendingEvents = this._pendingEventList.map(event => {
1322+
return {
1323+
...event.event,
1324+
txn_id: event.getTxnId(),
1325+
};
1326+
}).filter(event => {
1327+
// Filter out the unencrypted messages if the room is encrypted
1328+
const isEventEncrypted = event.type === "m.room.encrypted";
1329+
const isRoomEncrypted = this._client.isRoomEncrypted(this.roomId);
1330+
return isEventEncrypted || !isRoomEncrypted;
1331+
});
1332+
1333+
const { store } = this._client._sessionStore;
1334+
if (this._pendingEventList.length > 0) {
1335+
store.setItem(
1336+
pendingEventsKey(this.roomId),
1337+
JSON.stringify(pendingEvents),
1338+
);
1339+
} else {
1340+
store.removeItem(pendingEventsKey(this.roomId));
1341+
}
1342+
}
1343+
};
1344+
13151345
/**
13161346
* Used to aggregate the local echo for a relation, and also
13171347
* for re-applying a relation after it's redaction has been cancelled,
@@ -1472,9 +1502,6 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
14721502
for (let i = 0; i < this._timelineSets.length; i++) {
14731503
this._timelineSets[i].replaceEventId(oldEventId, newEventId);
14741504
}
1475-
if (this._opts.pendingEventOrdering === "detached") {
1476-
this.removePendingEvent(event.event.event_id);
1477-
}
14781505
} else if (newStatus == EventStatus.CANCELLED) {
14791506
// remove it from the pending event list, or the timeline.
14801507
if (this._pendingEventList) {
@@ -1488,6 +1515,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
14881515
}
14891516
this.removeEvent(oldEventId);
14901517
}
1518+
this._savePendingEvents();
14911519

14921520
this.emit("Room.localEchoUpdated", event, this, oldEventId, oldStatus);
14931521
};

0 commit comments

Comments
 (0)