Skip to content

Commit b3795d9

Browse files
committed
Fix showing edited message for historical messages
Fixes #713
1 parent 8c603ad commit b3795d9

File tree

1 file changed

+50
-43
lines changed

1 file changed

+50
-43
lines changed

Quotient/room.cpp

+50-43
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ class Q_DECL_HIDDEN Room::Private {
361361

362362
bool isLocalUser(const User* u) const { return u == q->localUser(); }
363363

364+
void processRedactionsAndEdits(RoomEvents& events);
365+
364366
#ifdef Quotient_E2EE_ENABLED
365367
UnorderedMap<QByteArray, QOlmInboundGroupSession> groupSessions;
366368
Omittable<QOlmOutboundGroupSession> currentOutboundMegolmSession = none;
@@ -2878,6 +2880,51 @@ inline bool isEditing(const RoomEventPtr& ep)
28782880
false);
28792881
}
28802882

2883+
void Room::Private::processRedactionsAndEdits(RoomEvents& events)
2884+
{
2885+
// Pre-process redactions and edits so that events that get
2886+
// redacted/replaced in the same batch landed in the timeline already
2887+
// treated.
2888+
// NB: We have to store redacting/replacing events to the timeline too -
2889+
// see #220.
2890+
auto it = std::find_if(events.begin(), events.end(), isEditing);
2891+
for (const auto& eptr : RoomEventsRange(it, events.end())) {
2892+
if (auto* r = eventCast<RedactionEvent>(eptr)) {
2893+
// Try to find the target in the timeline, then in the batch.
2894+
if (processRedaction(*r))
2895+
continue;
2896+
if (auto targetIt = std::find_if(events.begin(), events.end(),
2897+
[id = r->redactedEvent()](const RoomEventPtr& ep) {
2898+
return ep->id() == id;
2899+
}); targetIt != events.end())
2900+
*targetIt = makeRedacted(**targetIt, *r);
2901+
else
2902+
qCDebug(STATE)
2903+
<< "Redaction" << r->id() << "ignored: target event"
2904+
<< r->redactedEvent() << "is not found";
2905+
// If the target event comes later, it comes already redacted.
2906+
}
2907+
if (auto* msg = eventCast<RoomMessageEvent>(eptr);
2908+
msg && !msg->replacedEvent().isEmpty()) {
2909+
if (processReplacement(*msg))
2910+
continue;
2911+
auto targetIt = std::find_if(events.begin(), events.end(),
2912+
[id = msg->replacedEvent()](const RoomEventPtr& ep) {
2913+
return ep->id() == id;
2914+
});
2915+
if (targetIt != events.end())
2916+
*targetIt = makeReplaced(**targetIt, *msg);
2917+
else // FIXME: hide the replacing event when target arrives later
2918+
qCDebug(EVENTS)
2919+
<< "Replacing event" << msg->id()
2920+
<< "ignored: target event" << msg->replacedEvent()
2921+
<< "is not found";
2922+
// Same as with redactions above, the replaced event coming
2923+
// later will come already with the new content.
2924+
}
2925+
}
2926+
}
2927+
28812928
Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
28822929
{
28832930
dropExtraneousEvents(events);
@@ -2889,49 +2936,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
28892936
QElapsedTimer et;
28902937
et.start();
28912938

2892-
{
2893-
// Pre-process redactions and edits so that events that get
2894-
// redacted/replaced in the same batch landed in the timeline already
2895-
// treated.
2896-
// NB: We have to store redacting/replacing events to the timeline too -
2897-
// see #220.
2898-
auto it = std::find_if(events.begin(), events.end(), isEditing);
2899-
for (const auto& eptr : RoomEventsRange(it, events.end())) {
2900-
if (auto* r = eventCast<RedactionEvent>(eptr)) {
2901-
// Try to find the target in the timeline, then in the batch.
2902-
if (processRedaction(*r))
2903-
continue;
2904-
if (auto targetIt = std::find_if(events.begin(), events.end(),
2905-
[id = r->redactedEvent()](const RoomEventPtr& ep) {
2906-
return ep->id() == id;
2907-
}); targetIt != events.end())
2908-
*targetIt = makeRedacted(**targetIt, *r);
2909-
else
2910-
qCDebug(STATE)
2911-
<< "Redaction" << r->id() << "ignored: target event"
2912-
<< r->redactedEvent() << "is not found";
2913-
// If the target event comes later, it comes already redacted.
2914-
}
2915-
if (auto* msg = eventCast<RoomMessageEvent>(eptr);
2916-
msg && !msg->replacedEvent().isEmpty()) {
2917-
if (processReplacement(*msg))
2918-
continue;
2919-
auto targetIt = std::find_if(events.begin(), it,
2920-
[id = msg->replacedEvent()](const RoomEventPtr& ep) {
2921-
return ep->id() == id;
2922-
});
2923-
if (targetIt != it)
2924-
*targetIt = makeReplaced(**targetIt, *msg);
2925-
else // FIXME: hide the replacing event when target arrives later
2926-
qCDebug(EVENTS)
2927-
<< "Replacing event" << msg->id()
2928-
<< "ignored: target event" << msg->replacedEvent()
2929-
<< "is not found";
2930-
// Same as with redactions above, the replaced event coming
2931-
// later will come already with the new content.
2932-
}
2933-
}
2934-
}
2939+
processRedactionsAndEdits(events);
29352940

29362941
// State changes arrive as a part of timeline; the current room state gets
29372942
// updated before merging events to the timeline because that's what
@@ -3034,6 +3039,8 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events)
30343039

30353040
decryptIncomingEvents(events);
30363041

3042+
processRedactionsAndEdits(events);
3043+
30373044
QElapsedTimer et;
30383045
et.start();
30393046
Changes changes {};

0 commit comments

Comments
 (0)