Merge branch 'main' into android

This commit is contained in:
zaaach 2026-03-23 22:52:57 -04:00
commit cf2150466e
27 changed files with 423 additions and 312 deletions

View file

@ -0,0 +1,44 @@
import "dart:async";
import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/members_controller.dart";
import "package:nexus/models/configs/author_config.dart";
import "package:nexus/models/membership.dart";
class AuthorController extends AsyncNotifier<Membership> {
final AuthorConfig config;
AuthorController(this.config);
@override
Future<Membership> build() async {
var member = await ref.watch(
MembersController.provider(config.room).selectAsync(
(value) => value.firstWhereOrNull(
(membership) => membership.userId == config.message.authorId,
),
),
);
final pmp = config.message.metadata?["pmp"] == null
? null
: Membership.fromContent(
IMap(config.message.metadata?["pmp"]),
config.message.authorId,
);
return Membership(
avatarUrl: pmp?.avatarUrl ?? member?.avatarUrl,
displayName:
pmp?.displayName ??
member?.displayName ??
config.message.authorId.substring(1).split(":").first,
userId: config.message.authorId,
);
}
static final provider = AsyncNotifierProvider.family
.autoDispose<AuthorController, Membership, AuthorConfig>(
AuthorController.new,
);
}

View file

@ -1,25 +1,39 @@
import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/models/event.dart";
import "package:nexus/controllers/client_controller.dart";
import "package:nexus/models/membership.dart";
import "package:nexus/models/requests/get_room_state_request.dart";
import "package:nexus/models/room.dart";
class MembersController extends Notifier<IList<Event>> {
class MembersController extends AsyncNotifier<IList<Membership>> {
final Room room;
MembersController(this.room);
@override
IList<Event> build() => (room.state["m.room.member"]?.values ?? [])
.map(
(eventRowId) =>
room.events.firstWhereOrNull((event) => event.rowId == eventRowId),
)
.nonNulls
.where((member) => member.content["membership"] == "join")
.toIList();
Future<IList<Membership>> build() async {
if (room.metadata == null) return const IList.empty();
static final provider = NotifierProvider.family
.autoDispose<MembersController, IList<Event>, Room>(
final state = await ref
.watch(ClientController.provider.notifier)
.getRoomState(
GetRoomStateRequest(
roomId: room.metadata!.id,
fetchMembers: room.metadata!.hasMemberList == false,
includeMembers: true,
),
);
return state.nonNulls
.where((member) => member.content["membership"] == "join")
.map(
(membership) =>
Membership.fromContent(membership.content, membership.stateKey!),
)
.toIList();
}
static final provider =
AsyncNotifierProvider.family<MembersController, IList<Membership>, Room>(
MembersController.new,
);
}

View file

@ -2,9 +2,8 @@ import "package:collection/collection.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client_state_controller.dart";
import "package:nexus/controllers/members_controller.dart";
import "package:nexus/helpers/extensions/mxc_to_https.dart";
import "package:nexus/models/message_config.dart";
import "package:nexus/models/configs/message_config.dart";
class MessageController extends AsyncNotifier<Message?> {
final MessageConfig config;
@ -27,12 +26,6 @@ class MessageController extends AsyncNotifier<Message?> {
if (!ref.mounted) return null;
final members = ref.read(MembersController.provider(config.room));
final author = members.firstWhereOrNull(
(member) => member.stateKey == event.authorId,
);
if (!ref.mounted) return null;
final content = (event.decrypted ?? event.content);
final type = (config.event.decryptedType ?? config.event.type);
final newContent = content["m.new_content"] as Map?;
@ -52,14 +45,11 @@ class MessageController extends AsyncNotifier<Message?> {
"timelineId": event.timelineRowId,
"big": event.localContent?.bigEmoji == true,
"eventType": type,
"avatarUrl": author?.content["avatar_url"],
"pmp": event.content["com.beeper.per_message_profile"],
"editSource":
event.localContent?.editSource ??
newContent?["body"] ??
content["body"],
"displayName": author?.content["displayname"]?.isNotEmpty == true
? author?.content["displayname"]
: event.authorId.substring(1).split(":")[0],
"txnId": config.event.transactionId,
};

View file

@ -2,8 +2,8 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/message_controller.dart";
import "package:nexus/models/message_config.dart";
import "package:nexus/models/messages_config.dart";
import "package:nexus/models/configs/message_config.dart";
import "package:nexus/models/configs/messages_config.dart";
class MessagesController extends AsyncNotifier<IList<Message>> {
final MessagesConfig config;

View file

@ -1,5 +1,4 @@
import "dart:async";
import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
@ -11,8 +10,8 @@ import "package:nexus/controllers/message_controller.dart";
import "package:nexus/controllers/messages_controller.dart";
import "package:nexus/controllers/new_events_controller.dart";
import "package:nexus/controllers/rooms_controller.dart";
import "package:nexus/models/message_config.dart";
import "package:nexus/models/messages_config.dart";
import "package:nexus/models/configs/messages_config.dart";
import "package:nexus/models/configs/message_config.dart";
import "package:nexus/models/requests/get_room_state_request.dart";
import "package:nexus/models/requests/paginate_request.dart";
import "package:nexus/models/requests/redact_event_request.dart";
@ -31,11 +30,7 @@ class RoomChatController extends AsyncNotifier<InMemoryChatController> {
if (room == null) return InMemoryChatController();
final state = await client.getRoomState(
GetRoomStateRequest(
roomId: roomId,
fetchMembers: room.metadata?.hasMemberList == false,
includeMembers: true,
),
GetRoomStateRequest(roomId: roomId),
);
ref

View file

@ -36,6 +36,7 @@ class RoomsController extends Notifier<IMap<String, Room>> {
return acc.add(
roomId,
existing?.copyWith(
hasMore: incoming.hasMore,
metadata: incoming.metadata ?? existing.metadata,
events: events!,
state: incoming.state.entries.fold(