fix up bugs related to new architecture

This commit is contained in:
Henry Hiles 2026-05-17 22:24:41 -04:00
commit cb22ed9822
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
13 changed files with 48 additions and 27 deletions

View file

@ -80,7 +80,7 @@ class ClientController extends AsyncNotifier<int> {
case "send_complete":
final event = Event.fromJson(decodedMuksEvent["event"]);
if (event.type == EventType.message) {
if (event.type == EventType.message.type) {
// ref.watch(provider.notifier).addEvent(event); TODO
}
break;

View file

@ -28,7 +28,9 @@ class MembersController extends AsyncNotifier<IList<Event>> {
),
);
return state.where((state) => state.type == EventType.membership).toIList();
return state
.where((state) => state.type == EventType.membership.type)
.toIList();
}
static final provider =

View file

@ -57,7 +57,7 @@ class RoomChatController extends AsyncNotifier<IList<Event>> {
if (room == null) return const IList.empty();
// While there are under 30 messages, try up to load more messages until there's no more or we have 20 messages.
if (room.hasMore && room.events.length < 30) {
if (room.hasMore && room.timeline.length < 30) {
loadOlder();
}

View file

@ -1,3 +1,3 @@
extension GetLocalpart on String {
String get localpart => substring(1).split(":").first;
String get localpart => length > 1 ? substring(1).split(":").first : "?";
}

View file

@ -20,9 +20,9 @@ class Content {
factory Content.fromJson(Map<String, dynamic> json) => Content();
Map<String, dynamic> toJson() => {};
static Content fromEventJson(Map<String, dynamic> eventJson) =>
static Content fromEventJson(Map<String, dynamic> eventJson, String type) =>
(EventType.values
.firstWhereOrNull((eventType) => eventType.type == eventJson["type"])
.firstWhereOrNull((eventType) => eventType.type == type)
?.contentFromJson ??
Content.fromJson)(eventJson);
}

View file

@ -19,7 +19,7 @@ abstract class CreateContent extends Content with _$CreateContent {
@JsonKey(name: "m.federate") @Default(true) bool federated,
@Default("1") String roomVersion,
required String type,
String? type,
}) = _CreateContent;
factory CreateContent.fromJson(Map<String, Object?> json) =>
@ -28,7 +28,7 @@ abstract class CreateContent extends Content with _$CreateContent {
@freezed
abstract class PreviousRoom with _$PreviousRoom {
const factory PreviousRoom({required int roomId}) = _PreviousRoom;
const factory PreviousRoom({required String roomId}) = _PreviousRoom;
factory PreviousRoom.fromJson(Map<String, Object?> json) =>
_$PreviousRoomFromJson(json);

View file

@ -8,7 +8,7 @@ part "membership.g.dart";
abstract class MembershipContent extends Content with _$MembershipContent {
MembershipContent._();
factory MembershipContent({
@JsonKey(name: "displayname") required String displayName,
@JsonKey(name: "displayname") required String? displayName,
@JsonKey(name: "membership") required MembershipStatus status,
Uri? avatarUrl,
String? reason,

View file

@ -9,13 +9,22 @@ part "message.g.dart";
@Freezed(unionKey: "msgtype", fallbackUnion: "default")
abstract class MessageContent extends Content with _$MessageContent {
MessageContent._();
factory MessageContent({
required String msgtype,
factory MessageContent({required String body}) = UnknownMessageContent;
@FreezedUnionValue("m.text")
factory MessageContent.text({
required String body,
String? format,
String? formattedBody,
}) = TextMessageContent;
@FreezedUnionValue("m.notice")
factory MessageContent.notice({
required String body,
String? format,
String? formattedBody,
}) = NoticeMessageContent;
@FreezedUnionValue("m.image")
factory MessageContent.image({
required String body,

View file

@ -36,10 +36,13 @@ abstract class Event with _$Event {
@JsonKey(name: "last_edit_rowid") int? lastEditRowId,
@UnreadTypeConverter() UnreadType? unreadType,
@JsonKey(fromJson: pmpFromJson) Profile? pmp,
@JsonKey(fromJson: Content.fromEventJson) required Content content,
@JsonKey(fromJson: Content.fromJson) required Content content,
}) = _Event;
factory Event.fromJson(Map<String, Object?> json) => _$EventFromJson(json);
factory Event.fromJson(Map<String, dynamic> json) =>
_$EventFromJson(json).copyWith(
content: Content.fromEventJson(json["content"], json["type"] as String),
);
}
@freezed

View file

@ -4,6 +4,7 @@ import "package:nexus/controllers/members_by_type_controller.dart";
import "package:nexus/controllers/rooms_controller.dart";
import "package:nexus/controllers/via_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/helpers/extensions/get_localpart.dart";
import "package:nexus/models/content/membership.dart";
import "package:nexus/models/membership_status.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
@ -55,7 +56,7 @@ class MentionOverlay extends ConsumerWidget {
:final displayName,
) =>
displayName
.toLowerCase()
?.toLowerCase()
.contains(
query.toLowerCase(),
) ==
@ -72,16 +73,17 @@ class MentionOverlay extends ConsumerWidget {
ListTile(
leading: AvatarOrHash(
avatarUrl,
displayName,
displayName ??
member.stateKey!.localpart,
),
title: Text(
displayName ??
member.stateKey!.localpart,
),
title: Text(displayName),
subtitle: Text(member.stateKey!),
onTap: () => addTag(
id: "[@$displayName](matrix:u/${member.stateKey!.substring(1)})",
name: member.stateKey!
.substring(1)
.split(":")
.first,
name: member.stateKey!.localpart,
),
),
_ => SizedBox.shrink(),

View file

@ -2,8 +2,8 @@ import "package:flutter/material.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/author_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/helpers/extensions/get_localpart.dart";
import "package:nexus/helpers/extensions/show_user_popover.dart";
import "package:nexus/models/content/membership.dart";
import "package:nexus/models/event.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
@ -26,11 +26,11 @@ class MessageAvatar extends ConsumerWidget {
},
child: AvatarOrHash(
membership.avatarUrl,
membership.displayName,
membership.displayName ?? event.sender.localpart,
height: height,
),
),
loading: () =>
AvatarOrHash(null, event.sender.substring(1), height: height),
AvatarOrHash(null, event.sender.localpart, height: height),
);
}

View file

@ -3,6 +3,7 @@ import "package:flutter_hooks/flutter_hooks.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/members_by_type_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/helpers/extensions/get_localpart.dart";
import "package:nexus/helpers/extensions/show_user_popover.dart";
import "package:nexus/models/content/membership.dart";
import "package:nexus/models/membership_status.dart";
@ -75,9 +76,12 @@ class MemberList extends HookConsumerWidget {
globalPosition: details.globalPosition,
),
child: ListTile(
leading: AvatarOrHash(avatarUrl, displayName),
leading: AvatarOrHash(
avatarUrl,
displayName ?? member.sender.localpart,
),
title: Text(
displayName,
displayName ?? member.stateKey!.localpart,
overflow: TextOverflow.ellipsis,
),
subtitle: Text(

View file

@ -8,6 +8,7 @@ import "package:nexus/controllers/power_level_controller.dart";
import "package:nexus/controllers/profile_controller.dart";
import "package:nexus/controllers/selected_room_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/helpers/extensions/get_localpart.dart";
import "package:nexus/models/configs/power_level_config.dart";
import "package:nexus/models/content/membership.dart";
import "package:nexus/models/membership_status.dart";
@ -93,7 +94,7 @@ class UserPopover extends ConsumerWidget {
member.avatarUrl?.toString(),
child: AvatarOrHash(
member.avatarUrl,
member.displayName,
member.displayName ?? userId.localpart,
height: 80,
),
),
@ -101,7 +102,7 @@ class UserPopover extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
member.displayName,
member.displayName ?? userId.localpart,
style: textTheme.headlineSmall,
),
SelectableText(userId, style: textTheme.titleSmall),