From 5941cb9fd5502c4ff45e398dbf31875061eff65a Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Mon, 16 Sep 2024 19:50:49 +0800 Subject: [PATCH] :bug: Fix messages loading --- lib/controllers/chat_events_controller.dart | 41 +++++++++++++++---- lib/models/packet.dart | 2 +- lib/models/packet.g.dart | 2 +- lib/providers/database/services/messages.dart | 8 ++++ lib/widgets/chat/chat_event_list.dart | 11 +++-- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/lib/controllers/chat_events_controller.dart b/lib/controllers/chat_events_controller.dart index 9d649ed..9bd81e8 100644 --- a/lib/controllers/chat_events_controller.dart +++ b/lib/controllers/chat_events_controller.dart @@ -1,3 +1,5 @@ +import 'dart:math' as math; + import 'package:get/get.dart'; import 'package:solian/models/channel.dart'; import 'package:solian/models/event.dart'; @@ -30,14 +32,31 @@ class ChatEventController { this.channel = channel; this.scope = scope; - isLoading.value = true; - await syncLocal(channel, take: 10); + const firstTake = 20; + const furtherTake = 100; - src.pullRemoteEvents(channel, scope: scope, take: 10).then((result) { - totalEvents.value = result?.$2 ?? 0; - syncLocal(channel, take: 10); - }); + isLoading.value = true; + await syncLocal(channel, take: firstTake); isLoading.value = false; + + // Take a small range of messages to check is local database up to date + var isUpToDate = true; + final result = + await src.pullRemoteEvents(channel, scope: scope, take: firstTake); + totalEvents.value = result?.$2 ?? 0; + if ((result?.$1.length ?? 0) > 0) { + final minId = result!.$1.map((x) => x.id).reduce(math.min); + isUpToDate = await src.getEventFromLocal(minId) != null; + } + syncLocal(channel, take: firstTake); + + if (!isUpToDate) { + // Loading more content due to isn't up to date + final result = + await src.pullRemoteEvents(channel, scope: scope, take: furtherTake); + totalEvents.value = result?.$2 ?? 0; + syncLocal(channel, take: furtherTake); + } } Future loadEvents(Channel channel, String scope) async { @@ -46,7 +65,9 @@ class ChatEventController { isLoading.value = true; await syncLocal(channel, take: take, offset: offset); - src.pullRemoteEvents(channel, scope: scope, offset: offset).then((result) { + src + .pullRemoteEvents(channel, scope: scope, take: take, offset: offset) + .then((result) { totalEvents.value = result?.$2 ?? 0; syncLocal(channel, take: take, offset: offset); }); @@ -56,7 +77,11 @@ class ChatEventController { Future syncLocal(Channel channel, {required int take, int offset = 0}) async { final data = await src.listEvents(channel, take: take, offset: offset); - currentEvents.replaceRange(0, currentEvents.length, data); + if (currentEvents.length >= offset + take) { + currentEvents.replaceRange(offset, offset + take, data); + } else { + currentEvents.insertAll(currentEvents.length, data); + } for (final x in data.reversed) { applyEvent(x); } diff --git a/lib/models/packet.dart b/lib/models/packet.dart index 90341c5..230225d 100644 --- a/lib/models/packet.dart +++ b/lib/models/packet.dart @@ -4,7 +4,7 @@ part 'packet.g.dart'; @JsonSerializable() class NetworkPackage { - @JsonKey(name: 'w') + @JsonKey(name: 'w', defaultValue: 'unknown') String method; @JsonKey(name: 'e') String? endpoint; diff --git a/lib/models/packet.g.dart b/lib/models/packet.g.dart index 5c8d7ed..ef5ad90 100644 --- a/lib/models/packet.g.dart +++ b/lib/models/packet.g.dart @@ -8,7 +8,7 @@ part of 'packet.dart'; NetworkPackage _$NetworkPackageFromJson(Map json) => NetworkPackage( - method: json['w'] as String, + method: json['w'] as String? ?? 'unknown', endpoint: json['e'] as String?, message: json['m'] as String?, payload: json['p'] as Map?, diff --git a/lib/providers/database/services/messages.dart b/lib/providers/database/services/messages.dart index 8508c0c..e23ba99 100644 --- a/lib/providers/database/services/messages.dart +++ b/lib/providers/database/services/messages.dart @@ -129,6 +129,14 @@ class MessagesFetchingProvider extends GetxController { return await receiveEvent(remoteRecord); } + Future getEventFromLocal(int id) async { + final database = Get.find().database; + final localRecord = await (database.select(database.localMessageEventTable) + ..where((x) => x.id.equals(id))) + .getSingleOrNull(); + return localRecord; + } + /// Pull the remote events to local database Future<(List, int)?> pullRemoteEvents(Channel channel, {String scope = 'global', take = 10, offset = 0}) async { diff --git a/lib/widgets/chat/chat_event_list.dart b/lib/widgets/chat/chat_event_list.dart index a464e6d..a26d26a 100644 --- a/lib/widgets/chat/chat_event_list.dart +++ b/lib/widgets/chat/chat_event_list.dart @@ -92,10 +92,13 @@ class ChatEventList extends StatelessWidget { ); }, onFetchData: () { - chatController.loadEvents( - chatController.channel!, - chatController.scope!, - ); + if (chatController.currentEvents.length < + chatController.totalEvents.value) { + chatController.loadEvents( + chatController.channel!, + chatController.scope!, + ); + } }, ); }),