@@ -361,6 +361,8 @@ class Q_DECL_HIDDEN Room::Private {
361
361
362
362
bool isLocalUser (const User* u) const { return u == q->localUser (); }
363
363
364
+ void processRedactionsAndEdits (RoomEvents& events);
365
+
364
366
#ifdef Quotient_E2EE_ENABLED
365
367
UnorderedMap<QByteArray, QOlmInboundGroupSession> groupSessions;
366
368
Omittable<QOlmOutboundGroupSession> currentOutboundMegolmSession = none;
@@ -2878,6 +2880,51 @@ inline bool isEditing(const RoomEventPtr& ep)
2878
2880
false );
2879
2881
}
2880
2882
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
+
2881
2928
Room::Changes Room::Private::addNewMessageEvents (RoomEvents&& events)
2882
2929
{
2883
2930
dropExtraneousEvents (events);
@@ -2889,49 +2936,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
2889
2936
QElapsedTimer et;
2890
2937
et.start ();
2891
2938
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);
2935
2940
2936
2941
// State changes arrive as a part of timeline; the current room state gets
2937
2942
// updated before merging events to the timeline because that's what
@@ -3034,6 +3039,8 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events)
3034
3039
3035
3040
decryptIncomingEvents (events);
3036
3041
3042
+ processRedactionsAndEdits (events);
3043
+
3037
3044
QElapsedTimer et;
3038
3045
et.start ();
3039
3046
Changes changes {};
0 commit comments