Improve chat loading speed

This commit is contained in:
LittleSheep 2024-09-15 18:25:04 +08:00
parent c1ff317c66
commit 1437414b7f
4 changed files with 29 additions and 106 deletions

View File

@ -1,7 +1,6 @@
import 'package:get/get.dart';
import 'package:solian/models/channel.dart';
import 'package:solian/models/event.dart';
import 'package:solian/platform.dart';
import 'package:solian/providers/database/database.dart';
import 'package:solian/providers/database/services/messages.dart';
@ -31,79 +30,32 @@ class ChatEventController {
this.channel = channel;
this.scope = scope;
syncLocal(channel);
isLoading.value = true;
if (PlatformInfo.isWeb) {
final result = await src.fetchRemoteEvents(
channel,
scope,
depth: 1,
offset: 0,
);
await syncLocal(channel, take: 10);
src.pullRemoteEvents(channel, scope: scope, take: 10).then((result) {
totalEvents.value = result?.$2 ?? 0;
if (result != null) {
for (final x in result.$1.reversed) {
final entry = LocalMessageEventTableData(
id: x.id,
channelId: x.channelId,
createdAt: x.createdAt,
data: x,
);
insertEvent(entry);
applyEvent(entry);
}
}
} else {
final result = await src.pullRemoteEvents(
channel,
scope: scope,
depth: 1,
);
totalEvents.value = result?.$2 ?? 0;
await syncLocal(channel);
}
syncLocal(channel, take: 10);
});
isLoading.value = false;
}
Future<void> loadEvents(Channel channel, String scope) async {
const take = 20;
final offset = currentEvents.length;
isLoading.value = true;
if (PlatformInfo.isWeb) {
final result = await src.fetchRemoteEvents(
channel,
scope,
depth: 3,
offset: currentEvents.length,
);
if (result != null) {
totalEvents.value = result.$2;
for (final x in result.$1.reversed) {
final entry = LocalMessageEventTableData(
id: x.id,
channelId: x.channelId,
createdAt: x.createdAt,
data: x,
);
currentEvents.add(entry);
applyEvent(entry);
}
}
} else {
final result = await src.pullRemoteEvents(
channel,
depth: 3,
scope: scope,
offset: currentEvents.length,
);
await syncLocal(channel, take: take, offset: offset);
src.pullRemoteEvents(channel, scope: scope, offset: offset).then((result) {
totalEvents.value = result?.$2 ?? 0;
await syncLocal(channel);
}
syncLocal(channel, take: take, offset: offset);
});
isLoading.value = false;
}
Future<bool> syncLocal(Channel channel) async {
if (PlatformInfo.isWeb) return false;
final data = await src.listEvents(channel);
Future<bool> 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);
for (final x in data.reversed) {
applyEvent(x);
@ -113,16 +65,7 @@ class ChatEventController {
receiveEvent(Event remote) async {
LocalMessageEventTableData entry;
if (PlatformInfo.isWeb) {
entry = LocalMessageEventTableData(
id: remote.id,
channelId: remote.channelId,
createdAt: remote.createdAt,
data: remote,
);
} else {
entry = await src.receiveEvent(remote);
}
totalEvents.value++;
insertEvent(entry);

View File

@ -51,15 +51,9 @@ class MessagesFetchingProvider extends GetxController {
Future<(List<Event>, int)?> fetchRemoteEvents(
Channel channel,
String scope, {
required int depth,
bool Function(List<Event> items)? onBrake,
take = 10,
offset = 0,
}) async {
if (depth <= 0) {
return null;
}
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) return null;
@ -77,23 +71,9 @@ class MessagesFetchingProvider extends GetxController {
final result =
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
if (onBrake != null && onBrake(result)) {
return (result, response.count);
}
final expandResult = (await fetchRemoteEvents(
channel,
scope,
depth: depth - 1,
take: take,
offset: offset + result.length,
))
?.$1 ??
List.empty();
return ([...result, ...expandResult], response.count);
}
Future<LocalMessageEventTableData> receiveEvent(Event remote) async {
// Insert record
final database = Get.find<DatabaseProvider>().database;
@ -151,22 +131,14 @@ class MessagesFetchingProvider extends GetxController {
/// Pull the remote events to local database
Future<(List<Event>, int)?> pullRemoteEvents(Channel channel,
{String scope = 'global', depth = 10, offset = 0}) async {
{String scope = 'global', take = 10, offset = 0}) async {
final database = Get.find<DatabaseProvider>().database;
final lastOne = await (database.select(database.localMessageEventTable)
..where((x) => x.channelId.equals(channel.id))
..orderBy([(t) => OrderingTerm.desc(t.id)])
..limit(1))
.getSingleOrNull();
final data = await fetchRemoteEvents(
channel,
scope,
depth: depth,
offset: offset,
onBrake: (items) {
return items.any((x) => x.id == lastOne?.id);
},
take: take,
);
if (data != null) {
await database.batch((batch) {
@ -185,11 +157,13 @@ class MessagesFetchingProvider extends GetxController {
return data;
}
Future<List<LocalMessageEventTableData>> listEvents(Channel channel) async {
Future<List<LocalMessageEventTableData>> listEvents(Channel channel,
{required int take, int offset = 0}) async {
final database = Get.find<DatabaseProvider>().database;
return await (database.select(database.localMessageEventTable)
..where((x) => x.channelId.equals(channel.id))
..orderBy([(t) => OrderingTerm.desc(t.id)]))
..orderBy([(t) => OrderingTerm.desc(t.id)])
..limit(take, offset: offset))
.get();
}

View File

@ -274,6 +274,9 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer>
color: Theme.of(context).colorScheme.surface,
child: AppNavigationRegion(
isCollapsed: _isCollapsed,
onSelected: () {
_closeDrawer();
},
),
),
),

View File

@ -10,10 +10,12 @@ import 'package:solian/widgets/channel/channel_list.dart';
class AppNavigationRegion extends StatefulWidget {
final bool isCollapsed;
final Function onSelected;
const AppNavigationRegion({
super.key,
this.isCollapsed = false,
required this.onSelected,
});
@override
@ -204,6 +206,7 @@ class _AppNavigationRegionState extends State<AppNavigationRegion> {
isCollapsed: widget.isCollapsed,
selfId: auth.userProfile.value!['id'],
noCategory: true,
onSelected: (_) => widget.onSelected(),
),
),
),