⚡ Improve chat loading speed
This commit is contained in:
parent
c1ff317c66
commit
1437414b7f
@ -1,7 +1,6 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:solian/models/channel.dart';
|
import 'package:solian/models/channel.dart';
|
||||||
import 'package:solian/models/event.dart';
|
import 'package:solian/models/event.dart';
|
||||||
import 'package:solian/platform.dart';
|
|
||||||
import 'package:solian/providers/database/database.dart';
|
import 'package:solian/providers/database/database.dart';
|
||||||
import 'package:solian/providers/database/services/messages.dart';
|
import 'package:solian/providers/database/services/messages.dart';
|
||||||
|
|
||||||
@ -31,79 +30,32 @@ class ChatEventController {
|
|||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
|
|
||||||
syncLocal(channel);
|
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
if (PlatformInfo.isWeb) {
|
await syncLocal(channel, take: 10);
|
||||||
final result = await src.fetchRemoteEvents(
|
|
||||||
channel,
|
src.pullRemoteEvents(channel, scope: scope, take: 10).then((result) {
|
||||||
scope,
|
|
||||||
depth: 1,
|
|
||||||
offset: 0,
|
|
||||||
);
|
|
||||||
totalEvents.value = result?.$2 ?? 0;
|
totalEvents.value = result?.$2 ?? 0;
|
||||||
if (result != null) {
|
syncLocal(channel, take: 10);
|
||||||
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);
|
|
||||||
}
|
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadEvents(Channel channel, String scope) async {
|
Future<void> loadEvents(Channel channel, String scope) async {
|
||||||
|
const take = 20;
|
||||||
|
final offset = currentEvents.length;
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
if (PlatformInfo.isWeb) {
|
await syncLocal(channel, take: take, offset: offset);
|
||||||
final result = await src.fetchRemoteEvents(
|
src.pullRemoteEvents(channel, scope: scope, offset: offset).then((result) {
|
||||||
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,
|
|
||||||
);
|
|
||||||
totalEvents.value = result?.$2 ?? 0;
|
totalEvents.value = result?.$2 ?? 0;
|
||||||
await syncLocal(channel);
|
syncLocal(channel, take: take, offset: offset);
|
||||||
}
|
});
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> syncLocal(Channel channel) async {
|
Future<bool> syncLocal(Channel channel,
|
||||||
if (PlatformInfo.isWeb) return false;
|
{required int take, int offset = 0}) async {
|
||||||
final data = await src.listEvents(channel);
|
final data = await src.listEvents(channel, take: take, offset: offset);
|
||||||
currentEvents.replaceRange(0, currentEvents.length, data);
|
currentEvents.replaceRange(0, currentEvents.length, data);
|
||||||
for (final x in data.reversed) {
|
for (final x in data.reversed) {
|
||||||
applyEvent(x);
|
applyEvent(x);
|
||||||
@ -113,16 +65,7 @@ class ChatEventController {
|
|||||||
|
|
||||||
receiveEvent(Event remote) async {
|
receiveEvent(Event remote) async {
|
||||||
LocalMessageEventTableData entry;
|
LocalMessageEventTableData entry;
|
||||||
if (PlatformInfo.isWeb) {
|
entry = await src.receiveEvent(remote);
|
||||||
entry = LocalMessageEventTableData(
|
|
||||||
id: remote.id,
|
|
||||||
channelId: remote.channelId,
|
|
||||||
createdAt: remote.createdAt,
|
|
||||||
data: remote,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
entry = await src.receiveEvent(remote);
|
|
||||||
}
|
|
||||||
|
|
||||||
totalEvents.value++;
|
totalEvents.value++;
|
||||||
insertEvent(entry);
|
insertEvent(entry);
|
||||||
|
@ -51,15 +51,9 @@ class MessagesFetchingProvider extends GetxController {
|
|||||||
Future<(List<Event>, int)?> fetchRemoteEvents(
|
Future<(List<Event>, int)?> fetchRemoteEvents(
|
||||||
Channel channel,
|
Channel channel,
|
||||||
String scope, {
|
String scope, {
|
||||||
required int depth,
|
|
||||||
bool Function(List<Event> items)? onBrake,
|
|
||||||
take = 10,
|
take = 10,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
}) async {
|
}) async {
|
||||||
if (depth <= 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
if (auth.isAuthorized.isFalse) return null;
|
if (auth.isAuthorized.isFalse) return null;
|
||||||
|
|
||||||
@ -77,21 +71,7 @@ class MessagesFetchingProvider extends GetxController {
|
|||||||
final result =
|
final result =
|
||||||
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
|
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
|
||||||
|
|
||||||
if (onBrake != null && onBrake(result)) {
|
return (result, response.count);
|
||||||
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 {
|
Future<LocalMessageEventTableData> receiveEvent(Event remote) async {
|
||||||
@ -151,22 +131,14 @@ class MessagesFetchingProvider extends GetxController {
|
|||||||
|
|
||||||
/// Pull the remote events to local database
|
/// Pull the remote events to local database
|
||||||
Future<(List<Event>, int)?> pullRemoteEvents(Channel channel,
|
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 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(
|
final data = await fetchRemoteEvents(
|
||||||
channel,
|
channel,
|
||||||
scope,
|
scope,
|
||||||
depth: depth,
|
|
||||||
offset: offset,
|
offset: offset,
|
||||||
onBrake: (items) {
|
take: take,
|
||||||
return items.any((x) => x.id == lastOne?.id);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
await database.batch((batch) {
|
await database.batch((batch) {
|
||||||
@ -185,11 +157,13 @@ class MessagesFetchingProvider extends GetxController {
|
|||||||
return data;
|
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;
|
final database = Get.find<DatabaseProvider>().database;
|
||||||
return await (database.select(database.localMessageEventTable)
|
return await (database.select(database.localMessageEventTable)
|
||||||
..where((x) => x.channelId.equals(channel.id))
|
..where((x) => x.channelId.equals(channel.id))
|
||||||
..orderBy([(t) => OrderingTerm.desc(t.id)]))
|
..orderBy([(t) => OrderingTerm.desc(t.id)])
|
||||||
|
..limit(take, offset: offset))
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +274,9 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer>
|
|||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: AppNavigationRegion(
|
child: AppNavigationRegion(
|
||||||
isCollapsed: _isCollapsed,
|
isCollapsed: _isCollapsed,
|
||||||
|
onSelected: () {
|
||||||
|
_closeDrawer();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -10,10 +10,12 @@ import 'package:solian/widgets/channel/channel_list.dart';
|
|||||||
|
|
||||||
class AppNavigationRegion extends StatefulWidget {
|
class AppNavigationRegion extends StatefulWidget {
|
||||||
final bool isCollapsed;
|
final bool isCollapsed;
|
||||||
|
final Function onSelected;
|
||||||
|
|
||||||
const AppNavigationRegion({
|
const AppNavigationRegion({
|
||||||
super.key,
|
super.key,
|
||||||
this.isCollapsed = false,
|
this.isCollapsed = false,
|
||||||
|
required this.onSelected,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -204,6 +206,7 @@ class _AppNavigationRegionState extends State<AppNavigationRegion> {
|
|||||||
isCollapsed: widget.isCollapsed,
|
isCollapsed: widget.isCollapsed,
|
||||||
selfId: auth.userProfile.value!['id'],
|
selfId: auth.userProfile.value!['id'],
|
||||||
noCategory: true,
|
noCategory: true,
|
||||||
|
onSelected: (_) => widget.onSelected(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user