aggregate events

This commit is contained in:
Henry Hiles 2025-12-23 18:11:33 -05:00
commit 29d050d40b
No known key found for this signature in database
4 changed files with 41 additions and 42 deletions

View file

@ -103,7 +103,6 @@ A simple and user-friendly Matrix client made with Flutter and the Matrix Dart S
## Known Bugs ## Known Bugs
- Sometimes we have errors on scrolling due to out of chunk edits. This will be easy to fix once https://forgejo.ellis.link/continuwuation/continuwuity/pulls/847 is complete and merged. I left a bounty on this, so hopefully it can get resolved quickly.
- Sometimes the app refreshes, I believe due to some controllers invalidating. This needs investigation as to why it happens. - Sometimes the app refreshes, I believe due to some controllers invalidating. This needs investigation as to why it happens.
- Sometimes links don't parse properly, this is apparent in the Maunium Ping Room. We might possibly need a regex change. - Sometimes links don't parse properly, this is apparent in the Maunium Ping Room. We might possibly need a regex change.

View file

@ -30,18 +30,17 @@ class RoomChatController extends AsyncNotifier<ChatController> {
), ),
); );
} else { } else {
final message = await event.toMessage(); final message = await event.toMessage(includeEdits: true);
if (event.relationshipType == RelationshipTypes.edit) {
final controller = await future;
final oldMessage = controller.messages.firstWhereOrNull(
(element) => element.id == event.relationshipEventId,
);
if (oldMessage == null || message == null) return;
return await updateMessage(oldMessage, message);
}
if (message != null) { if (message != null) {
if (event.relationshipType == RelationshipTypes.edit) { return await insertMessage(message);
final controller = await future;
final oldMessage = controller.messages.firstWhereOrNull(
(element) => element.id == event.relationshipEventId,
);
if (oldMessage == null) return;
await updateMessage(oldMessage, message);
} else {
await insertMessage(message);
}
} }
} }
}).cancel, }).cancel,

View file

@ -4,33 +4,39 @@ import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:matrix/matrix.dart"; import "package:matrix/matrix.dart";
extension EventToMessage on Event { extension EventToMessage on Event {
Future<Message?> toMessage({bool mustBeText = false}) async { Future<Message?> toMessage({
bool mustBeText = false,
bool includeEdits = false,
}) async {
final replyId = relationshipType == RelationshipTypes.reply final replyId = relationshipType == RelationshipTypes.reply
? relationshipEventId ? relationshipEventId
: null; : null;
final sender = (await fetchSenderUser()) ?? senderFromMemoryOrFallback;
final newContent = content["m.new_content"] as Map<String, Object?>?; final newEvent = (unsigned?["m.relations"] as Map?)?["m.replace"];
final event = newEvent == null ? this : Event.fromJson(newEvent, room);
final newContent = event.content["m.new_content"] as Map?;
final metadata = { final metadata = {
"formatted": "formatted":
newContent?["formatted_body"] ?? newContent?["formatted_body"] ??
newContent?["body"] ?? newContent?["body"] ??
content["formatted_body"] ?? event.content["formatted_body"] ??
this.body, event.content["body"],
"eventType": type, "eventType": event.type,
"displayName": sender.displayName ?? sender.id, "displayName":
event.senderFromMemoryOrFallback.displayName ??
event.senderFromMemoryOrFallback.id,
"txnId": transactionId, "txnId": transactionId,
}; };
final editedAt = relationshipType == RelationshipTypes.edit final editedAt = event.relationshipType == RelationshipTypes.edit
? originServerTs ? event.originServerTs
: null; : null;
final body = (newContent?["body"] ?? content["body"]).toString();
final eventId = editedAt == null
? this.eventId
: relationshipEventId ?? this.eventId;
if (redacted && !mustBeText) return null; if ((redacted && !mustBeText) ||
(!includeEdits && (relationshipType == RelationshipTypes.edit))) {
return null;
}
// TODO: Use server-generated preview if enabled when https://github.com/famedly/matrix-dart-sdk/issues/2195 is fixed. // TODO: Use server-generated preview if enabled when https://github.com/famedly/matrix-dart-sdk/issues/2195 is fixed.
@ -47,7 +53,7 @@ extension EventToMessage on Event {
metadata: metadata, metadata: metadata,
id: eventId, id: eventId,
authorId: senderId, authorId: senderId,
text: body, text: redacted ? "This message has been deleted..." : event.body,
replyToMessageId: replyId, replyToMessageId: replyId,
deliveredAt: originServerTs, deliveredAt: originServerTs,
editedAt: editedAt, editedAt: editedAt,
@ -66,7 +72,7 @@ extension EventToMessage on Event {
metadata: metadata, metadata: metadata,
id: eventId, id: eventId,
authorId: senderId, authorId: senderId,
text: text, text: event.text,
source: (await getAttachmentUri()).toString(), source: (await getAttachmentUri()).toString(),
replyToMessageId: replyId, replyToMessageId: replyId,
deliveredAt: originServerTs, deliveredAt: originServerTs,
@ -75,18 +81,19 @@ extension EventToMessage on Event {
metadata: metadata, metadata: metadata,
id: eventId, id: eventId,
authorId: senderId, authorId: senderId,
text: text, text: event.text,
replyToMessageId: replyId, replyToMessageId: replyId,
source: (await getAttachmentUri()).toString(), source: (await event.getAttachmentUri()).toString(),
deliveredAt: originServerTs, deliveredAt: originServerTs,
// TODO: See if we can figure out duration
duration: Duration(hours: 1), duration: Duration(hours: 1),
), ),
MessageTypes.File => Message.file( MessageTypes.File => Message.file(
name: content["filename"].toString(), name: event.content["filename"].toString(),
metadata: metadata, metadata: metadata,
id: eventId, id: eventId,
authorId: senderId, authorId: senderId,
source: (await getAttachmentUri()).toString(), source: (await event.getAttachmentUri()).toString(),
replyToMessageId: replyId, replyToMessageId: replyId,
deliveredAt: originServerTs, deliveredAt: originServerTs,
), ),
@ -97,7 +104,7 @@ extension EventToMessage on Event {
id: eventId, id: eventId,
authorId: senderId, authorId: senderId,
text: text:
"${sender.displayName} ${switch (Membership.values.firstWhereOrNull((membership) => membership.name == content["membership"])) { "${event.senderFromMemoryOrFallback.displayName} ${switch (Membership.values.firstWhereOrNull((membership) => membership.name == event.content["membership"])) {
Membership.invite => "was invited to", Membership.invite => "was invited to",
Membership.join => "joined", Membership.join => "joined",
Membership.leave => "left", Membership.leave => "left",

View file

@ -3,13 +3,7 @@ import "package:matrix/matrix.dart";
import "package:nexus/helpers/extensions/event_to_message.dart"; import "package:nexus/helpers/extensions/event_to_message.dart";
extension ListToMessages on List<MatrixEvent> { extension ListToMessages on List<MatrixEvent> {
Future<List<Message>> toMessages(Room room) async { Future<List<Message>> toMessages(Room room) async => (await Future.wait(
final messages = await Future.wait( map((event) => Event.fromMatrixEvent(event, room).toMessage()),
map((event) => Event.fromMatrixEvent(event, room).toMessage()), )).nonNulls.toList().reversed.toList();
);
return {
for (var msg in messages.nonNulls.toList().reversed.toList()) msg.id: msg,
}.values.toList();
}
} }