diff --git a/lib/src/client.dart b/lib/src/client.dart index 0bdcedaa..b8b31060 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -190,6 +190,7 @@ class Client extends MatrixApi { EventTypes.Message, EventTypes.Encrypted, EventTypes.Sticker, + EventTypes.Reaction, ]); // register all the default commands diff --git a/lib/src/room.dart b/lib/src/room.dart index f9d0a4e9..93ff6aa9 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -167,11 +167,7 @@ class Room { return; } - final isMessageEvent = [ - EventTypes.Message, - EventTypes.Sticker, - EventTypes.Encrypted, - ].contains(state.type); + final isMessageEvent = client.roomPreviewLastEvents.contains(state.type); // We ignore events editing events older than the current-latest here so // i.e. newly sent edits for older events don't show up in room preview @@ -514,9 +510,19 @@ class Room { /// Checks if the last event has a read marker of the user. bool get hasNewMessages { final lastEvent = this.lastEvent; - return lastEvent != null && - !lastEvent.receipts - .any((receipt) => receipt.user.senderId == client.userID!); + + // There is no known event or the last event is only a state fallback event, + // we assume there is no new messages. + if (lastEvent == null || + !client.roomPreviewLastEvents.contains(lastEvent.type)) return false; + + // Read marker is on the last event so no new messages. + if (lastEvent.receipts + .any((receipt) => receipt.user.senderId == client.userID!)) { + return false; + } + + return true; } /// Returns true if this room is unread. To check if there are new messages diff --git a/lib/src/utils/event_localizations.dart b/lib/src/utils/event_localizations.dart index 385a1d3f..64d1f3e6 100644 --- a/lib/src/utils/event_localizations.dart +++ b/lib/src/utils/event_localizations.dart @@ -213,7 +213,12 @@ abstract class EventLocalizations { _localizedBodyNormalMessage(event, i18n, body), EventTypes.Message: (event, i18n, body) => _localizedBodyNormalMessage(event, i18n, body), - EventTypes.Reaction: (event, i18n, body) => - _localizedBodyNormalMessage(event, i18n, body), + EventTypes.Reaction: (event, i18n, body) => i18n.sentReaction( + event.sender.calcDisplayname(), + event.content + .tryGetMap('m.relates_to') + ?.tryGet('key') ?? + body, + ), }; } diff --git a/lib/src/utils/matrix_localizations.dart b/lib/src/utils/matrix_localizations.dart index 9b0aaa56..3db5e3e3 100644 --- a/lib/src/utils/matrix_localizations.dart +++ b/lib/src/utils/matrix_localizations.dart @@ -122,6 +122,8 @@ abstract class MatrixLocalizations { String sentAVideo(String senderName); + String sentReaction(String senderName, String reactionKey); + String sharedTheLocation(String senderName); String couldNotDecryptMessage(String errorText); diff --git a/test/matrix_default_localizations.dart b/test/matrix_default_localizations.dart index 3ab973ff..4b356960 100644 --- a/test/matrix_default_localizations.dart +++ b/test/matrix_default_localizations.dart @@ -225,4 +225,9 @@ class MatrixDefaultLocalizations extends MatrixLocalizations { String startedACall(String senderName) { return 'startedACall'; } + + @override + String sentReaction(String senderName, String reactionKey) { + return '$senderName reacted with $reactionKey'; + } } diff --git a/test/room_test.dart b/test/room_test.dart index 867f196a..ffd49630 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -258,6 +258,26 @@ void main() { expect(room.lastEvent?.eventId, '5'); expect(room.lastEvent?.body, 'edited cdc'); expect(room.lastEvent?.status, EventStatus.sent); + // Are reactions coming through? + room.setState( + Event( + senderId: '@test:example.com', + type: EventTypes.Reaction, + room: room, + eventId: '123456', + originServerTs: DateTime.now(), + content: { + 'm.relates_to': { + 'rel_type': RelationshipTypes.reaction, + 'event_id': '1234', + 'key': ':-)', + } + }, + stateKey: '', + ), + ); + expect(room.lastEvent?.eventId, '123456'); + expect(room.lastEvent?.type, EventTypes.Reaction); }); test('lastEvent when reply parent edited', () async { room.setState(