big performance improvements!!
This commit is contained in:
parent
4acf624bff
commit
2d90a2adfe
8 changed files with 86 additions and 45 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import "dart:developer";
|
import "dart:developer";
|
||||||
import "dart:ffi";
|
import "dart:ffi";
|
||||||
import "dart:isolate";
|
import "dart:isolate";
|
||||||
|
import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:flutter/foundation.dart";
|
import "package:flutter/foundation.dart";
|
||||||
|
|
@ -170,8 +171,12 @@ class ClientController extends AsyncNotifier<int> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Event?> getEvent(GetEventRequest request) async {
|
Future<Event?> getEvent(GetEventRequest request) async {
|
||||||
final json = await _sendCommand("get_event", request.toJson());
|
final event = request.room.events.firstWhereOrNull(
|
||||||
|
(event) => event.eventId == request.eventId,
|
||||||
|
);
|
||||||
|
if (event != null) return event;
|
||||||
|
|
||||||
|
final json = await _sendCommand("get_event", request.toJson());
|
||||||
return json == null ? null : Event.fromJson(json);
|
return json == null ? null : Event.fromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "package:collection/collection.dart";
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/client_controller.dart";
|
import "package:nexus/controllers/client_controller.dart";
|
||||||
|
|
@ -6,7 +7,6 @@ import "package:nexus/controllers/profile_controller.dart";
|
||||||
import "package:nexus/helpers/extensions/mxc_to_https.dart";
|
import "package:nexus/helpers/extensions/mxc_to_https.dart";
|
||||||
import "package:nexus/models/message_config.dart";
|
import "package:nexus/models/message_config.dart";
|
||||||
import "package:nexus/models/requests/get_event_request.dart";
|
import "package:nexus/models/requests/get_event_request.dart";
|
||||||
import "package:nexus/models/requests/get_related_events_request.dart";
|
|
||||||
|
|
||||||
class MessageController extends AsyncNotifier<Message?> {
|
class MessageController extends AsyncNotifier<Message?> {
|
||||||
final MessageConfig config;
|
final MessageConfig config;
|
||||||
|
|
@ -19,22 +19,20 @@ class MessageController extends AsyncNotifier<Message?> {
|
||||||
}
|
}
|
||||||
final client = ref.watch(ClientController.provider.notifier);
|
final client = ref.watch(ClientController.provider.notifier);
|
||||||
|
|
||||||
final newEvents = await client.getRelatedEvents(
|
|
||||||
GetRelatedEventsRequest(
|
|
||||||
roomId: config.event.roomId,
|
|
||||||
eventId: config.event.eventId,
|
|
||||||
relationType: "m.replace",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (!ref.mounted) return null;
|
if (!ref.mounted) return null;
|
||||||
final event = newEvents?.lastOrNull ?? config.event;
|
final event = config.event.lastEditRowId == null
|
||||||
|
? config.event
|
||||||
|
: config.room.events.firstWhereOrNull(
|
||||||
|
(e) => e.rowId == config.event.lastEditRowId,
|
||||||
|
) ??
|
||||||
|
config.event;
|
||||||
|
|
||||||
final replyId =
|
final replyId =
|
||||||
config.event.content["m.relates_to"]?["m.in_reply_to"]?["event_id"];
|
config.event.content["m.relates_to"]?["m.in_reply_to"]?["event_id"];
|
||||||
final replyEvent = replyId == null
|
final replyEvent = replyId == null
|
||||||
? null
|
? null
|
||||||
: await client.getEvent(
|
: await client.getEvent(
|
||||||
GetEventRequest(roomId: config.event.roomId, eventId: replyId),
|
GetEventRequest(room: config.room, eventId: replyId),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!ref.mounted) return null;
|
if (!ref.mounted) return null;
|
||||||
|
|
@ -58,7 +56,11 @@ class MessageController extends AsyncNotifier<Message?> {
|
||||||
if (replyEvent != null)
|
if (replyEvent != null)
|
||||||
"reply": await ref.watch(
|
"reply": await ref.watch(
|
||||||
MessageController.provider(
|
MessageController.provider(
|
||||||
MessageConfig(event: replyEvent, mustBeText: true),
|
MessageConfig(
|
||||||
|
event: replyEvent,
|
||||||
|
room: config.room,
|
||||||
|
mustBeText: true,
|
||||||
|
),
|
||||||
).future,
|
).future,
|
||||||
),
|
),
|
||||||
"body": newContent?["body"] ?? content["body"],
|
"body": newContent?["body"] ?? content["body"],
|
||||||
|
|
@ -152,21 +154,24 @@ class MessageController extends AsyncNotifier<Message?> {
|
||||||
),
|
),
|
||||||
_ => asText,
|
_ => asText,
|
||||||
},
|
},
|
||||||
"m.room.member" => Message.system(
|
"m.room.member" =>
|
||||||
metadata: metadata,
|
content["membership"] == event.unsigned["prev_content"]?["membership"]
|
||||||
id: config.event.eventId,
|
? null
|
||||||
authorId: event.authorId,
|
: Message.system(
|
||||||
deliveredAt: config.event.timestamp,
|
metadata: metadata,
|
||||||
text:
|
id: config.event.eventId,
|
||||||
"${content["displayname"] ?? event.stateKey} ${switch (content["membership"]) {
|
authorId: event.authorId,
|
||||||
"invite" => "was invited to",
|
deliveredAt: config.event.timestamp,
|
||||||
"join" => "joined",
|
text:
|
||||||
"leave" => "left",
|
"${content["displayname"] ?? event.stateKey} ${switch (content["membership"]) {
|
||||||
"knock" => "asked to join",
|
"invite" => "was invited to",
|
||||||
"ban" => "was banned from",
|
"join" => "joined",
|
||||||
_ => "did something relating to",
|
"leave" => "left",
|
||||||
}} the room.",
|
"knock" => "asked to join",
|
||||||
),
|
"ban" => "was banned from",
|
||||||
|
_ => "did something relating to",
|
||||||
|
}} the room.",
|
||||||
|
),
|
||||||
"m.room.redaction" => null,
|
"m.room.redaction" => null,
|
||||||
_ =>
|
_ =>
|
||||||
// Turn this on for debugging purposes
|
// Turn this on for debugging purposes
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,26 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/message_controller.dart";
|
import "package:nexus/controllers/message_controller.dart";
|
||||||
import "package:nexus/models/event.dart";
|
|
||||||
import "package:nexus/models/message_config.dart";
|
import "package:nexus/models/message_config.dart";
|
||||||
|
import "package:nexus/models/messages_config.dart";
|
||||||
|
|
||||||
class MessagesController extends AsyncNotifier<IList<Message>> {
|
class MessagesController extends AsyncNotifier<IList<Message>> {
|
||||||
final IList<Event> events;
|
final MessagesConfig config;
|
||||||
MessagesController(this.events);
|
MessagesController(this.config);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<IList<Message>> build() async => (await Future.wait(
|
Future<IList<Message>> build() async => (await Future.wait(
|
||||||
events.map(
|
config.events.map(
|
||||||
(event) => ref.watch(
|
(event) => ref.watch(
|
||||||
MessageController.provider(MessageConfig(event: event)).future,
|
MessageController.provider(
|
||||||
|
MessageConfig(event: event, room: config.room),
|
||||||
|
).future,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)).nonNulls.toIList();
|
)).nonNulls.toIList();
|
||||||
|
|
||||||
static final provider = AsyncNotifierProvider.family
|
static final provider = AsyncNotifierProvider.family
|
||||||
.autoDispose<MessagesController, IList<Message>, IList<Event>>(
|
.autoDispose<MessagesController, IList<Message>, MessagesConfig>(
|
||||||
MessagesController.new,
|
MessagesController.new,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import "package:nexus/controllers/new_events_controller.dart";
|
||||||
import "package:nexus/controllers/rooms_controller.dart";
|
import "package:nexus/controllers/rooms_controller.dart";
|
||||||
import "package:nexus/controllers/selected_room_controller.dart";
|
import "package:nexus/controllers/selected_room_controller.dart";
|
||||||
import "package:nexus/models/message_config.dart";
|
import "package:nexus/models/message_config.dart";
|
||||||
|
import "package:nexus/models/messages_config.dart";
|
||||||
import "package:nexus/models/requests/get_room_state_request.dart";
|
import "package:nexus/models/requests/get_room_state_request.dart";
|
||||||
import "package:nexus/models/requests/paginate_request.dart";
|
import "package:nexus/models/requests/paginate_request.dart";
|
||||||
import "package:nexus/models/requests/redact_event_request.dart";
|
import "package:nexus/models/requests/redact_event_request.dart";
|
||||||
|
|
@ -30,14 +31,17 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
|
|
||||||
final messages = await ref.watch(
|
final messages = await ref.watch(
|
||||||
MessagesController.provider(
|
MessagesController.provider(
|
||||||
room.timeline
|
MessagesConfig(
|
||||||
.map(
|
room: room,
|
||||||
(timelineRowTuple) => room.events.firstWhereOrNull(
|
events: room.timeline
|
||||||
(event) => event.rowId == timelineRowTuple.eventRowId,
|
.map(
|
||||||
),
|
(timelineRowTuple) => room.events.firstWhereOrNull(
|
||||||
)
|
(event) => event.rowId == timelineRowTuple.eventRowId,
|
||||||
.nonNulls
|
),
|
||||||
.toIList(),
|
)
|
||||||
|
.nonNulls
|
||||||
|
.toIList(),
|
||||||
|
),
|
||||||
).future,
|
).future,
|
||||||
);
|
);
|
||||||
final controller = InMemoryChatController(messages: messages.toList());
|
final controller = InMemoryChatController(messages: messages.toList());
|
||||||
|
|
@ -57,7 +61,7 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
} else {
|
} else {
|
||||||
final message = await ref.watch(
|
final message = await ref.watch(
|
||||||
MessageController.provider(
|
MessageController.provider(
|
||||||
MessageConfig(event: event, includeEdits: true),
|
MessageConfig(event: event, room: room, includeEdits: true),
|
||||||
).future,
|
).future,
|
||||||
);
|
);
|
||||||
if (event.relationType == "m.replace") {
|
if (event.relationType == "m.replace") {
|
||||||
|
|
@ -191,8 +195,13 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
const ISet.empty(),
|
const ISet.empty(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final room = ref.watch(RoomsController.provider)[roomId];
|
||||||
|
if (room == null) return;
|
||||||
|
|
||||||
final messages = await ref.watch(
|
final messages = await ref.watch(
|
||||||
MessagesController.provider(response.events.reversed).future,
|
MessagesController.provider(
|
||||||
|
MessagesConfig(room: room, events: response.events.reversed),
|
||||||
|
).future,
|
||||||
);
|
);
|
||||||
await controller.insertAllMessages(
|
await controller.insertAllMessages(
|
||||||
messages
|
messages
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ abstract class Event with _$Event {
|
||||||
String? decryptionError,
|
String? decryptionError,
|
||||||
String? sendError,
|
String? sendError,
|
||||||
@Default(IMap.empty()) IMap<String, int> reactions,
|
@Default(IMap.empty()) IMap<String, int> reactions,
|
||||||
int? lastEditRowId,
|
@JsonKey(name: "last_edit_rowid") int? lastEditRowId,
|
||||||
@UnreadTypeConverter() UnreadType? unreadType,
|
@UnreadTypeConverter() UnreadType? unreadType,
|
||||||
}) = _Event;
|
}) = _Event;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import "package:freezed_annotation/freezed_annotation.dart";
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/models/room.dart";
|
||||||
part "message_config.freezed.dart";
|
part "message_config.freezed.dart";
|
||||||
part "message_config.g.dart";
|
part "message_config.g.dart";
|
||||||
|
|
||||||
|
|
@ -8,6 +9,7 @@ abstract class MessageConfig with _$MessageConfig {
|
||||||
const factory MessageConfig({
|
const factory MessageConfig({
|
||||||
@Default(false) bool mustBeText,
|
@Default(false) bool mustBeText,
|
||||||
@Default(false) bool includeEdits,
|
@Default(false) bool includeEdits,
|
||||||
|
required Room room,
|
||||||
required Event event,
|
required Event event,
|
||||||
}) = _MessageConfig;
|
}) = _MessageConfig;
|
||||||
|
|
||||||
|
|
|
||||||
17
lib/models/messages_config.dart
Normal file
17
lib/models/messages_config.dart
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/models/room.dart";
|
||||||
|
part "messages_config.freezed.dart";
|
||||||
|
part "messages_config.g.dart";
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class MessagesConfig with _$MessagesConfig {
|
||||||
|
const factory MessagesConfig({
|
||||||
|
required Room room,
|
||||||
|
required IList<Event> events,
|
||||||
|
}) = _MessagesConfig;
|
||||||
|
|
||||||
|
factory MessagesConfig.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$MessagesConfigFromJson(json);
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import "package:freezed_annotation/freezed_annotation.dart";
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
import "package:nexus/models/room.dart";
|
||||||
part "get_event_request.freezed.dart";
|
part "get_event_request.freezed.dart";
|
||||||
part "get_event_request.g.dart";
|
part "get_event_request.g.dart";
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class GetEventRequest with _$GetEventRequest {
|
abstract class GetEventRequest with _$GetEventRequest {
|
||||||
const factory GetEventRequest({
|
const factory GetEventRequest({
|
||||||
required String roomId,
|
required Room room,
|
||||||
required String eventId,
|
required String eventId,
|
||||||
@Default(false) bool unredact,
|
@Default(false) bool unredact,
|
||||||
}) = _GetEventRequest;
|
}) = _GetEventRequest;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue