don't pass room around, use many watches

This commit is contained in:
Henry Hiles 2026-03-29 14:14:11 -04:00
commit 60be7aaf72
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
15 changed files with 207 additions and 231 deletions

View file

@ -1,31 +1,31 @@
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";
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/models/configs/author_config.dart";
import "package:nexus/models/membership.dart";
class AuthorController extends AsyncNotifier<Membership> {
final AuthorConfig config;
AuthorController(this.config);
final Message message;
AuthorController(this.message);
@override
Future<Membership> build() async {
final member = await ref.watch(
MembersController.provider(config.room).selectAsync(
MembersController.provider.selectAsync(
(value) => value.firstWhereOrNull(
(membership) => membership.userId == config.message.authorId,
(membership) => membership.userId == message.authorId,
),
),
);
final pmp = config.message.metadata?["pmp"] == null
final pmp = message.metadata?["pmp"] == null
? null
: Membership.fromContent(
IMap(config.message.metadata?["pmp"]),
config.message.authorId,
IMap(message.metadata?["pmp"]),
message.authorId,
ref.watch(
ClientStateController.provider.select(
(value) => value?.homeserverUrl,
@ -39,12 +39,13 @@ class AuthorController extends AsyncNotifier<Membership> {
displayName:
pmp?.displayName ??
member?.displayName ??
config.message.authorId.substring(1).split(":").first,
userId: config.message.authorId,
message.authorId.substring(1).split(":").first,
userId: message.authorId,
);
}
static final provider = AsyncNotifierProvider.family<AuthorController, Membership, AuthorConfig>(
static final provider =
AsyncNotifierProvider.family<AuthorController, Membership, Message>(
AuthorController.new,
);
}

View file

@ -2,24 +2,28 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client_controller.dart";
import "package:nexus/controllers/client_state_controller.dart";
import "package:nexus/controllers/selected_room_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 AsyncNotifier<IList<Membership>> {
final Room room;
MembersController(this.room);
@override
Future<IList<Membership>> build() async {
if (room.metadata == null) return const IList.empty();
final data = ref.watch(
SelectedRoomController.provider.select(
(value) => value?.metadata == null
? null
: (value!.metadata!.id, value.metadata!.hasMemberList),
),
);
if (data == null) return const IList.empty();
final state = await ref
.watch(ClientController.provider.notifier)
.getRoomState(
GetRoomStateRequest(
roomId: room.metadata!.id,
fetchMembers: room.metadata!.hasMemberList == false,
roomId: data.$1,
fetchMembers: data.$2 == false,
includeMembers: true,
),
);
@ -42,7 +46,7 @@ class MembersController extends AsyncNotifier<IList<Membership>> {
}
static final provider =
AsyncNotifierProvider.family<MembersController, IList<Membership>, Room>(
AsyncNotifierProvider<MembersController, IList<Membership>>(
MembersController.new,
);
}

View file

@ -223,13 +223,13 @@ class RoomChatController extends AsyncNotifier<InMemoryChatController> {
}
Future<void> send(
String message, {
String text, {
bool shouldMention = true,
required Iterable<Tag> tags,
required IList<Tag> tags,
required RelationType relationType,
Message? relation,
}) async {
var taggedMessage = message;
var taggedMessage = text;
for (final tag in tags) {
final escaped = RegExp.escape(tag.id);

View file

@ -1,14 +0,0 @@
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/room.dart";
part "author_config.freezed.dart";
part "author_config.g.dart";
@freezed
abstract class AuthorConfig with _$AuthorConfig {
const factory AuthorConfig({required Message message, required Room room}) =
_AuthorConfig;
factory AuthorConfig.fromJson(Map<String, Object?> json) =>
_$AuthorConfigFromJson(json);
}

View file

@ -1,12 +1,11 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:flutter_hooks/flutter_hooks.dart";
import "package:fluttertagger/fluttertagger.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/room_chat_controller.dart";
import "package:nexus/models/relation_type.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/chat_page/composer/mention_overlay.dart";
import "package:nexus/widgets/chat_page/composer/relation_preview.dart";
@ -14,12 +13,17 @@ class ChatBox extends HookConsumerWidget {
final Message? relatedMessage;
final RelationType relationType;
final VoidCallback onDismiss;
final Room room;
final Future<void> Function(
String text, {
required bool shouldMention,
required IList<Tag> tags,
})
onSend;
const ChatBox({
required this.relatedMessage,
required this.relationType,
required this.onDismiss,
required this.room,
required this.onSend,
super.key,
});
@ -38,16 +42,12 @@ class ChatBox extends HookConsumerWidget {
}
void send() {
if (controller.value.text.trim().isEmpty || room.metadata == null) return;
ref
.watch(RoomChatController.provider(room.metadata!.id).notifier)
.send(
controller.value.formattedText,
shouldMention: shouldMention.value,
relation: relatedMessage,
relationType: relationType,
tags: controller.value.tags,
);
onSend(
controller.value.formattedText,
shouldMention: shouldMention.value,
tags: controller.value.tags.toIList(),
);
onDismiss();
controller.value.text = "";
}
@ -81,7 +81,6 @@ class ChatBox extends HookConsumerWidget {
children: [
RelationPreview(
relatedMessage,
room: room,
shouldMention: shouldMention.value,
toggleShouldMention: () =>
shouldMention.value = !shouldMention.value,
@ -123,7 +122,6 @@ class ChatBox extends HookConsumerWidget {
child: FlutterTagger(
triggerStrategy: TriggerStrategy.eager,
overlay: MentionOverlay(
room,
query: query.value,
triggerCharacter: triggerCharacter.value,
addTag: ({required id, required name}) {

View file

@ -3,17 +3,14 @@ import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/members_controller.dart";
import "package:nexus/controllers/rooms_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
import "package:nexus/widgets/loading.dart";
class MentionOverlay extends ConsumerWidget {
final String? triggerCharacter;
final String query;
final Room room;
final void Function({required String id, required String name}) addTag;
const MentionOverlay(
this.room, {
const MentionOverlay({
required this.query,
required this.addTag,
required this.triggerCharacter,
@ -34,7 +31,7 @@ class MentionOverlay extends ConsumerWidget {
child: switch (triggerCharacter) {
"@" =>
ref
.watch(MembersController.provider(room))
.watch(MembersController.provider)
.betterWhen(
data: (members) => ListView(
children:

View file

@ -2,7 +2,6 @@ import "package:flutter/material.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/models/relation_type.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/chat_page/lazy_loading/message_avatar.dart";
import "package:nexus/widgets/chat_page/lazy_loading/message_displayname.dart";
@ -12,11 +11,9 @@ class RelationPreview extends ConsumerWidget {
final VoidCallback onDismiss;
final bool shouldMention;
final VoidCallback toggleShouldMention;
final Room room;
const RelationPreview(
this.relatedMessage, {
required this.room,
required this.relationType,
required this.onDismiss,
required this.shouldMention,
@ -41,10 +38,9 @@ class RelationPreview extends ConsumerWidget {
"Editing message:",
style: TextStyle(fontWeight: FontWeight.bold),
),
MessageAvatar(relatedMessage!, room),
MessageAvatar(relatedMessage!),
MessageDisplayname(
relatedMessage!,
room,
style: theme.textTheme.labelMedium?.copyWith(
fontWeight: FontWeight.bold,
),

View file

@ -3,21 +3,16 @@ import "package:flutter_chat_core/flutter_chat_core.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/models/configs/author_config.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
class MessageAvatar extends ConsumerWidget {
final Message message;
final Room room;
final double height;
const MessageAvatar(this.message, this.room, {this.height = 16, super.key});
const MessageAvatar(this.message, {this.height = 16, super.key});
@override
Widget build(BuildContext context, WidgetRef ref) => ref
.watch(
AuthorController.provider(AuthorConfig(room: room, message: message)),
)
.watch(AuthorController.provider(message))
.betterWhen(
data: (membership) => AvatarOrHash(
membership.avatarUrl,

View file

@ -3,20 +3,15 @@ import "package:flutter_chat_core/flutter_chat_core.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/models/configs/author_config.dart";
import "package:nexus/models/room.dart";
class MessageDisplayname extends ConsumerWidget {
final Message message;
final Room room;
final TextStyle? style;
const MessageDisplayname(this.message, this.room, {this.style, super.key});
const MessageDisplayname(this.message, {this.style, super.key});
@override
Widget build(BuildContext context, WidgetRef ref) => ref
.watch(
AuthorController.provider(AuthorConfig(room: room, message: message)),
)
.watch(AuthorController.provider(message))
.betterWhen(
data: (membership) => Text(
"${membership.displayName} ${message.metadata?["pmp"] == null ? "" : "(via ${message.authorId})"}",

View file

@ -2,16 +2,14 @@ import "package:flutter/material.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/members_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
class MemberList extends ConsumerWidget {
final Room room;
const MemberList(this.room, {super.key});
const MemberList({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final membersProvider = ref.watch(MembersController.provider(room));
final membersProvider = ref.watch(MembersController.provider);
return Drawer(
shape: Border(),
child: Column(

View file

@ -3,10 +3,10 @@ import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/event_controller.dart";
import "package:nexus/controllers/message_controller.dart";
import "package:nexus/controllers/selected_room_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/models/configs/message_config.dart";
import "package:nexus/models/requests/get_event_request.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/chat_page/html/quoted.dart";
import "package:nexus/widgets/chat_page/lazy_loading/message_avatar.dart";
import "package:nexus/widgets/chat_page/lazy_loading/message_displayname.dart";
@ -16,12 +16,10 @@ typedef OnTapReply = void Function(Message message)?;
class ReplyWidget extends ConsumerWidget {
final Message message;
final bool alwaysShow;
final Room room;
final MessageGroupStatus? groupStatus;
final OnTapReply onTapReply;
const ReplyWidget(
this.message, {
required this.room,
required this.groupStatus,
this.onTapReply,
this.alwaysShow = false,
@ -29,73 +27,74 @@ class ReplyWidget extends ConsumerWidget {
});
@override
Widget build(BuildContext context, WidgetRef ref) =>
message.replyToMessageId == null
? SizedBox.shrink()
: Padding(
padding: EdgeInsets.only(bottom: 12),
child: Quoted(
ref
.watch(
EventController.provider(
GetEventRequest(
room: room,
eventId: message.replyToMessageId!,
Widget build(BuildContext context, WidgetRef ref) {
final room = ref.watch(SelectedRoomController.provider);
return message.replyToMessageId == null || room == null
? SizedBox.shrink()
: Padding(
padding: EdgeInsets.only(bottom: 12),
child: Quoted(
ref
.watch(
EventController.provider(
GetEventRequest(
room: room,
eventId: message.replyToMessageId!,
),
),
),
)
.betterWhen(
loading: () => Text("Fetching event..."),
data: (event) => event == null
? SizedBox.shrink()
: ref
.watch(
MessageController.provider(
MessageConfig(room: room, event: event),
),
)
.betterWhen(
loading: () => Text("Parsing message..."),
data: (replyMessage) {
if (replyMessage == null) {
return SizedBox.shrink();
}
)
.betterWhen(
loading: () => Text("Fetching event..."),
data: (event) => event == null
? SizedBox.shrink()
: ref
.watch(
MessageController.provider(
MessageConfig(room: room, event: event),
),
)
.betterWhen(
loading: () => Text("Parsing message..."),
data: (replyMessage) {
if (replyMessage == null) {
return SizedBox.shrink();
}
return InkWell(
onTap: () => onTapReply?.call(replyMessage),
child: Row(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
MessageAvatar(replyMessage, room),
Flexible(
child: MessageDisplayname(
replyMessage,
room,
style: Theme.of(context)
.textTheme
.labelMedium
?.copyWith(
fontWeight: FontWeight.bold,
),
return InkWell(
onTap: () => onTapReply?.call(replyMessage),
child: Row(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
MessageAvatar(replyMessage),
Flexible(
child: MessageDisplayname(
replyMessage,
style: Theme.of(context)
.textTheme
.labelMedium
?.copyWith(
fontWeight: FontWeight.bold,
),
),
),
),
Flexible(
child: Text(
replyMessage.metadata!["body"],
overflow: TextOverflow.ellipsis,
style: Theme.of(
context,
).textTheme.labelMedium,
maxLines: 1,
Flexible(
child: Text(
replyMessage.metadata!["body"],
overflow: TextOverflow.ellipsis,
style: Theme.of(
context,
).textTheme.labelMedium,
maxLines: 1,
),
),
),
],
),
);
},
),
),
),
);
],
),
);
},
),
),
),
);
}
}

View file

@ -1,18 +1,17 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:nexus/models/room.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/selected_room_controller.dart";
import "package:nexus/widgets/appbar.dart";
import "package:nexus/widgets/avatar_or_hash.dart";
import "package:nexus/widgets/chat_page/expandable_image.dart";
import "package:nexus/widgets/chat_page/room_menu.dart";
class RoomAppbar extends StatelessWidget implements PreferredSizeWidget {
class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
final bool isDesktop;
final Room room;
final void Function(BuildContext context) onOpenMemberList;
final void Function(BuildContext context) onOpenDrawer;
const RoomAppbar(
this.room, {
const RoomAppbar({
required this.isDesktop,
required this.onOpenMemberList,
required this.onOpenDrawer,
@ -23,50 +22,53 @@ class RoomAppbar extends StatelessWidget implements PreferredSizeWidget {
Size get preferredSize => AppBar().preferredSize;
@override
Widget build(BuildContext context) => Appbar(
leading: isDesktop
? ExpandableImage(
room.metadata?.avatar?.toString(),
child: AvatarOrHash(
room.metadata?.avatar,
room.metadata?.name ?? "Unnamed Rooms",
height: 24,
fallback: Icon(Icons.numbers),
),
)
: DrawerButton(onPressed: () => onOpenDrawer(context)),
scrolledUnderElevation: 0,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
room.metadata?.name ?? "Unnamed Room",
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
if (room.metadata?.topic?.isNotEmpty == true)
Widget build(BuildContext context, WidgetRef ref) {
final room = ref.watch(SelectedRoomController.provider)!;
return Appbar(
leading: isDesktop
? ExpandableImage(
room.metadata?.avatar?.toString(),
child: AvatarOrHash(
room.metadata?.avatar,
room.metadata?.name ?? "Unnamed Rooms",
height: 24,
fallback: Icon(Icons.numbers),
),
)
: DrawerButton(onPressed: () => onOpenDrawer(context)),
scrolledUnderElevation: 0,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
room.metadata!.topic!,
maxLines: 1,
room.metadata?.name ?? "Unnamed Room",
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.labelMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
maxLines: 1,
),
],
),
actions: [
IconButton(
onPressed: null,
icon: Icon(Icons.push_pin),
tooltip: "Open pinned messages",
if (room.metadata?.topic?.isNotEmpty == true)
Text(
room.metadata!.topic!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.labelMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
IconButton(
onPressed: () => onOpenMemberList(context),
tooltip: "Open member list",
icon: Icon(Icons.people),
),
RoomMenu(room),
].toIList(),
);
actions: [
IconButton(
onPressed: null,
icon: Icon(Icons.push_pin),
tooltip: "Open pinned messages",
),
IconButton(
onPressed: () => onOpenMemberList(context),
tooltip: "Open member list",
icon: Icon(Icons.people),
),
RoomMenu(room),
].toIList(),
);
}
}

View file

@ -35,16 +35,18 @@ class RoomChat extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final client = ref.watch(ClientController.provider.notifier);
final replyToMessage = useState<Message?>(null);
final relatedMessage = useState<Message?>(null);
final memberListOpened = useState<bool>(showMembersByDefault);
final relationType = useState(RelationType.reply);
final room = ref.watch(SelectedRoomController.provider);
final userId = ref.watch(ClientStateController.provider)?.userId;
final roomId = ref.watch(
SelectedRoomController.provider.select((value) => value?.metadata?.id),
);
final theme = Theme.of(context);
final danger = theme.colorScheme.error;
if (room == null || userId == null || room.metadata?.id == null) {
if (roomId == null || userId == null) {
return Center(
child: Text(
"Nothing to see here...",
@ -53,7 +55,7 @@ class RoomChat extends HookConsumerWidget {
);
}
final controllerProvider = RoomChatController.provider(room.metadata!.id);
final controllerProvider = RoomChatController.provider(roomId);
final notifier = ref.watch(controllerProvider.notifier);
List<PopupMenuEntry> getMessageOptions(Message message) {
@ -61,7 +63,7 @@ class RoomChat extends HookConsumerWidget {
return [
PopupMenuItem(
onTap: () {
replyToMessage.value = message;
relatedMessage.value = message;
relationType.value = RelationType.reply;
},
child: ListTile(leading: Icon(Icons.reply), title: Text("Reply")),
@ -69,7 +71,7 @@ class RoomChat extends HookConsumerWidget {
if (message is TextMessage && isSentByMe)
PopupMenuItem(
onTap: () {
replyToMessage.value = message;
relatedMessage.value = message;
relationType.value = RelationType.edit;
},
child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")),
@ -153,10 +155,9 @@ class RoomChat extends HookConsumerWidget {
),
TextButton(
onPressed: () {
if (room.metadata == null) return;
client.reportEvent(
ReportRequest(
roomId: room.metadata!.id,
roomId: roomId,
eventId: message.id,
reason: reasonController.text.isEmpty
? null
@ -189,7 +190,6 @@ class RoomChat extends HookConsumerWidget {
return Scaffold(
appBar: RoomAppbar(
room,
isDesktop: isDesktop,
onOpenDrawer: (_) => Scaffold.of(context).openDrawer(),
onOpenMemberList: (thisContext) {
@ -237,18 +237,41 @@ class RoomChat extends HookConsumerWidget {
chatAnimatedListBuilder: (_, itemBuilder) =>
ChatAnimatedList(
itemBuilder: itemBuilder,
onEndReached: room.hasMore
onEndReached:
ref.watch(
SelectedRoomController.provider.select(
(room) => room?.hasMore == true,
),
)
? notifier.loadOlder
: null,
onStartReached: () => client.markRead(room),
onStartReached: () async {
final room = ref.watch(
SelectedRoomController.provider,
);
return room == null
? null
: await client.markRead(room);
},
bottomPadding: 72,
),
composerBuilder: (_) => ChatBox(
onSend:
(
text, {
required shouldMention,
required tags,
}) => notifier.send(
text,
tags: tags,
relationType: relationType.value,
shouldMention: shouldMention,
relation: relatedMessage.value,
),
relationType: relationType.value,
relatedMessage: replyToMessage.value,
onDismiss: () => replyToMessage.value = null,
room: room,
relatedMessage: relatedMessage.value,
onDismiss: () => relatedMessage.value = null,
),
textMessageBuilder:
@ -259,7 +282,6 @@ class RoomChat extends HookConsumerWidget {
required bool isSentByMe,
MessageGroupStatus? groupStatus,
}) => TextMessageWrapper(
room: room,
message,
content: message.text,
groupStatus: groupStatus,
@ -277,7 +299,6 @@ class RoomChat extends HookConsumerWidget {
MessageGroupStatus? groupStatus,
}) => TextMessageWrapper(
message,
room: room,
content: message.text,
groupStatus: groupStatus,
onTapReply: notifier.scrollToMessage,
@ -309,7 +330,6 @@ class RoomChat extends HookConsumerWidget {
),
child: FlyerChatFileMessage(
topWidget: ReplyWidget(
room: room,
message,
onTapReply: notifier.scrollToMessage,
groupStatus: groupStatus,
@ -319,7 +339,6 @@ class RoomChat extends HookConsumerWidget {
),
),
groupStatus,
room,
),
systemMessageBuilder:
@ -358,11 +377,11 @@ class RoomChat extends HookConsumerWidget {
),
if (memberListOpened.value == true && showMembersByDefault)
MemberList(room),
MemberList(),
],
),
endDrawer: showMembersByDefault ? null : MemberList(room),
endDrawer: showMembersByDefault ? null : MemberList(),
);
}
}

View file

@ -1,21 +1,13 @@
import "package:flutter/material.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/chat_page/lazy_loading/message_avatar.dart";
import "package:nexus/widgets/chat_page/lazy_loading/message_displayname.dart";
class MessageWrapper extends StatelessWidget {
final Message message;
final Widget child;
final Room room;
final MessageGroupStatus? groupStatus;
const MessageWrapper(
this.message,
this.child,
this.groupStatus,
this.room, {
super.key,
});
const MessageWrapper(this.message, this.child, this.groupStatus, {super.key});
@override
Widget build(BuildContext context) => ClipRRect(
@ -33,7 +25,7 @@ class MessageWrapper extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
groupStatus?.isFirst != false
? MessageAvatar(message, room, height: 40)
? MessageAvatar(message, height: 40)
: SizedBox(width: 40),
Expanded(
child: Column(
@ -43,7 +35,6 @@ class MessageWrapper extends StatelessWidget {
if (groupStatus?.isFirst != false)
MessageDisplayname(
message,
room,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),

View file

@ -1,7 +1,6 @@
import "package:flutter/material.dart";
import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:flutter_link_previewer/flutter_link_previewer.dart";
import "package:nexus/models/room.dart";
import "package:nexus/widgets/chat_page/html/html.dart";
import "package:nexus/widgets/chat_page/wrappers/message_wrapper.dart";
import "package:nexus/widgets/chat_page/reply_widget.dart";
@ -9,7 +8,6 @@ import "package:nexus/widgets/chat_page/reply_widget.dart";
class TextMessageWrapper extends StatelessWidget {
final Message message;
final String? content;
final Room room;
final MessageGroupStatus? groupStatus;
final Future<void> Function(Message oldMessage, Message newMessage)
updateMessage;
@ -21,7 +19,6 @@ class TextMessageWrapper extends StatelessWidget {
this.message, {
this.content,
this.onTapReply,
required this.room,
required this.updateMessage,
required this.groupStatus,
required this.isSentByMe,
@ -51,7 +48,6 @@ class TextMessageWrapper extends StatelessWidget {
children: [
ReplyWidget(
message,
room: room,
groupStatus: groupStatus,
onTapReply: onTapReply,
),
@ -109,7 +105,6 @@ class TextMessageWrapper extends StatelessWidget {
),
),
groupStatus,
room,
);
}
}