diff --git a/lib/src/event.dart b/lib/src/event.dart index df0aa03b..23c53ca0 100644 --- a/lib/src/event.dart +++ b/lib/src/event.dart @@ -715,4 +715,28 @@ class Event extends MatrixEvent { hasAggregatedEvents(timeline, type) ? timeline.aggregatedEvents[eventId][type] : {}; + + /// Fetches the event to be rendered, taking into account all the edits and the like. + /// It needs a [timeline] for that. + Event getDisplayEvent(Timeline timeline) { + if (hasAggregatedEvents(timeline, RelationshipTypes.Edit)) { + // alright, we have an edit + final allEditEvents = aggregatedEvents(timeline, RelationshipTypes.Edit) + // we only allow edits made by the original author themself + .where((e) => e.senderId == senderId && e.type == EventTypes.Message) + .toList(); + // we need to check again if it isn't empty, as we potentially removed all + // aggregated edits + if (allEditEvents.isNotEmpty) { + allEditEvents.sort((a, b) => a.sortOrder - b.sortOrder > 0 ? 1 : -1); + var rawEvent = allEditEvents.last.toJson(); + // update the content of the new event to render + if (rawEvent['content']['m.new_content'] is Map) { + rawEvent['content'] = rawEvent['content']['m.new_content']; + } + return Event.fromJson(rawEvent, room); + } + } + return this; + } } diff --git a/test/event_test.dart b/test/event_test.dart index 5fb041c0..e57be26d 100644 --- a/test/event_test.dart +++ b/test/event_test.dart @@ -873,5 +873,92 @@ void main() { expect( event.aggregatedEvents(timeline, RelationshipTypes.Edit), {}); }); + test('getDisplayEvent', () { + var event = Event.fromJson({ + 'type': EventTypes.Message, + 'content': { + 'body': 'blah', + 'msgtype': 'm.text', + }, + 'event_id': '\$source', + 'sender': '@alice:example.org', + }, null); + event.sortOrder = 0; + var edit1 = Event.fromJson({ + 'type': EventTypes.Message, + 'content': { + 'body': '* edit 1', + 'msgtype': 'm.text', + 'm.new_content': { + 'body': 'edit 1', + 'msgtype': 'm.text', + }, + 'm.relates_to': { + 'event_id': '\$source', + 'rel_type': RelationshipTypes.Edit, + }, + }, + 'event_id': '\$edit1', + 'sender': '@alice:example.org', + }, null); + edit1.sortOrder = 1; + var edit2 = Event.fromJson({ + 'type': EventTypes.Message, + 'content': { + 'body': '* edit 2', + 'msgtype': 'm.text', + 'm.new_content': { + 'body': 'edit 2', + 'msgtype': 'm.text', + }, + 'm.relates_to': { + 'event_id': '\$source', + 'rel_type': RelationshipTypes.Edit, + }, + }, + 'event_id': '\$edit2', + 'sender': '@alice:example.org', + }, null); + edit2.sortOrder = 2; + var edit3 = Event.fromJson({ + 'type': EventTypes.Message, + 'content': { + 'body': '* edit 3', + 'msgtype': 'm.text', + 'm.new_content': { + 'body': 'edit 3', + 'msgtype': 'm.text', + }, + 'm.relates_to': { + 'event_id': '\$source', + 'rel_type': RelationshipTypes.Edit, + }, + }, + 'event_id': '\$edit3', + 'sender': '@bob:example.org', + }, null); + edit3.sortOrder = 3; + var room = Room(client: client); + // no edits + var displayEvent = + event.getDisplayEvent(Timeline(events: [event], room: room)); + expect(displayEvent.body, 'blah'); + // one edit + displayEvent = event + .getDisplayEvent(Timeline(events: [event, edit1], room: room)); + expect(displayEvent.body, 'edit 1'); + // two edits + displayEvent = event.getDisplayEvent( + Timeline(events: [event, edit1, edit2], room: room)); + expect(displayEvent.body, 'edit 2'); + // foreign edit + displayEvent = event + .getDisplayEvent(Timeline(events: [event, edit3], room: room)); + expect(displayEvent.body, 'blah'); + // mixed foreign and non-foreign + displayEvent = event.getDisplayEvent( + Timeline(events: [event, edit1, edit2, edit3], room: room)); + expect(displayEvent.body, 'edit 2'); + }); }); }