fix bug in timeline

This commit is contained in:
Henry Hiles 2026-01-30 14:26:59 +01:00
commit 34f45c929a
No known key found for this signature in database
4 changed files with 36 additions and 19 deletions

View file

@ -27,6 +27,16 @@ class RoomChatController extends AsyncNotifier<ChatController> {
final room = ref.read(SelectedRoomController.provider); final room = ref.read(SelectedRoomController.provider);
if (room == null) return InMemoryChatController(); 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.onDispose(
ref.listen(NewEventsController.provider(roomId), (_, next) async { ref.listen(NewEventsController.provider(roomId), (_, next) async {
for (final event in next) { for (final event in next) {
@ -62,23 +72,17 @@ class RoomChatController extends AsyncNotifier<ChatController> {
), ),
); );
} }
if (message != null) { if (message != null &&
return await insertMessage(message); !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); ref.onDispose(controller.dispose);
if (messages.length < 20) await loadOlder(controller); if (messages.length < 20) await loadOlder(controller);

View file

@ -15,18 +15,29 @@ class RoomsController extends Notifier<IMap<String, Room>> {
final incoming = entry.value; final incoming = entry.value;
final existing = acc[roomId]; final existing = acc[roomId];
final events = existing?.events.updateById(
incoming.events,
(item) => item.eventId,
);
ref ref
.watch(NewEventsController.provider(roomId).notifier) .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( return acc.add(
roomId, roomId,
existing?.copyWith( existing?.copyWith(
metadata: incoming.metadata ?? existing.metadata, metadata: incoming.metadata ?? existing.metadata,
events: existing.events.updateById( events: events!,
incoming.events,
(item) => item.eventId,
),
state: incoming.state.entries.fold( state: incoming.state.entries.fold(
existing.state, existing.state,
(previousValue, event) => previousValue.add( (previousValue, event) => previousValue.add(

View file

@ -28,7 +28,7 @@ abstract class Room with _$Room {
abstract class TimelineRowTuple with _$TimelineRowTuple { abstract class TimelineRowTuple with _$TimelineRowTuple {
const factory TimelineRowTuple({ const factory TimelineRowTuple({
@JsonKey(name: "timeline_rowid") required int timelineRowId, @JsonKey(name: "timeline_rowid") required int timelineRowId,
@JsonKey(name: "timeline_eventid") int? eventRowId, @JsonKey(name: "event_rowid") int? eventRowId,
}) = _TimelineRowTuple; }) = _TimelineRowTuple;
factory TimelineRowTuple.fromJson(Map<String, Object?> json) => factory TimelineRowTuple.fromJson(Map<String, Object?> json) =>

View file

@ -267,7 +267,9 @@ class RoomChat extends HookConsumerWidget {
chatAnimatedListBuilder: (_, itemBuilder) => chatAnimatedListBuilder: (_, itemBuilder) =>
ChatAnimatedList( ChatAnimatedList(
itemBuilder: itemBuilder, itemBuilder: itemBuilder,
onEndReached: notifier.loadOlder, onEndReached: room.hasMore
? notifier.loadOlder
: null,
onStartReached: () => client.markRead(room), onStartReached: () => client.markRead(room),
bottomPadding: 72, bottomPadding: 72,
), ),