From 34f45c929a7c746f0e353f18737fd8b6942cf8d3 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 30 Jan 2026 14:26:59 +0100 Subject: [PATCH] fix bug in timeline --- lib/controllers/room_chat_controller.dart | 28 +++++++++++++---------- lib/controllers/rooms_controller.dart | 21 +++++++++++++---- lib/models/room.dart | 2 +- lib/widgets/chat_page/room_chat.dart | 4 +++- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index fc32be3..791a63c 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -27,6 +27,16 @@ class RoomChatController extends AsyncNotifier { final room = ref.read(SelectedRoomController.provider); if (room == null) return InMemoryChatController(); + final messages = await room.timeline + .map( + (timelineRowTuple) => room.events.firstWhereOrNull( + (event) => event.rowId == timelineRowTuple.eventRowId, + ), + ) + .nonNulls + .toMessages(ref); + final controller = InMemoryChatController(messages: messages); + ref.onDispose( ref.listen(NewEventsController.provider(roomId), (_, next) async { for (final event in next) { @@ -62,23 +72,17 @@ class RoomChatController extends AsyncNotifier { ), ); } - if (message != null) { - return await insertMessage(message); + if (message != null && + !controller.messages.any( + (oldMessage) => oldMessage.id == message.id, + )) { + await insertMessage(message); } } } - }).close, + }, weak: true).close, ); - final messages = await room.timeline - .map( - (timelineRowTuple) => room.events.firstWhereOrNull( - (event) => event.rowId == timelineRowTuple.eventRowId, - ), - ) - .nonNulls - .toMessages(ref); - final controller = InMemoryChatController(messages: messages); ref.onDispose(controller.dispose); if (messages.length < 20) await loadOlder(controller); diff --git a/lib/controllers/rooms_controller.dart b/lib/controllers/rooms_controller.dart index bc109c9..0945644 100644 --- a/lib/controllers/rooms_controller.dart +++ b/lib/controllers/rooms_controller.dart @@ -15,18 +15,29 @@ class RoomsController extends Notifier> { final incoming = entry.value; final existing = acc[roomId]; + final events = existing?.events.updateById( + incoming.events, + (item) => item.eventId, + ); + ref .watch(NewEventsController.provider(roomId).notifier) - .add(incoming.events); + .add( + incoming.timeline + .map( + (timelineTuple) => events?.firstWhereOrNull( + (event) => timelineTuple.eventRowId == event.rowId, + ), + ) + .nonNulls + .toIList(), + ); return acc.add( roomId, existing?.copyWith( metadata: incoming.metadata ?? existing.metadata, - events: existing.events.updateById( - incoming.events, - (item) => item.eventId, - ), + events: events!, state: incoming.state.entries.fold( existing.state, (previousValue, event) => previousValue.add( diff --git a/lib/models/room.dart b/lib/models/room.dart index b7ff81d..3c3eec0 100644 --- a/lib/models/room.dart +++ b/lib/models/room.dart @@ -28,7 +28,7 @@ abstract class Room with _$Room { abstract class TimelineRowTuple with _$TimelineRowTuple { const factory TimelineRowTuple({ @JsonKey(name: "timeline_rowid") required int timelineRowId, - @JsonKey(name: "timeline_eventid") int? eventRowId, + @JsonKey(name: "event_rowid") int? eventRowId, }) = _TimelineRowTuple; factory TimelineRowTuple.fromJson(Map json) => diff --git a/lib/widgets/chat_page/room_chat.dart b/lib/widgets/chat_page/room_chat.dart index d8d99c4..f7e6bc4 100644 --- a/lib/widgets/chat_page/room_chat.dart +++ b/lib/widgets/chat_page/room_chat.dart @@ -267,7 +267,9 @@ class RoomChat extends HookConsumerWidget { chatAnimatedListBuilder: (_, itemBuilder) => ChatAnimatedList( itemBuilder: itemBuilder, - onEndReached: notifier.loadOlder, + onEndReached: room.hasMore + ? notifier.loadOlder + : null, onStartReached: () => client.markRead(room), bottomPadding: 72, ),