add reply ui

This commit is contained in:
Henry Hiles 2025-11-12 21:57:50 -05:00
commit 8bc010cfc7
No known key found for this signature in database
2 changed files with 70 additions and 11 deletions

View file

@ -43,10 +43,10 @@ class RoomChatController extends AsyncNotifier<ChatController> {
return controller.updateMessage(message, newMessage); return controller.updateMessage(message, newMessage);
} }
Future<void> send(String message, {String? replyTo}) async => Future<void> send(String message, {Message? replyTo}) async =>
await room.sendTextEvent( await room.sendTextEvent(
message, message,
inReplyTo: replyTo == null ? null : await room.getEventById(replyTo), inReplyTo: replyTo == null ? null : await room.getEventById(replyTo.id),
); );
Future<chat.User> resolveUser(String id) async { Future<chat.User> resolveUser(String id) async {

View file

@ -38,7 +38,7 @@ class RoomChat extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final replyToMessageId = useState<String?>(null); final replyToMessage = useState<Message?>(null);
final urlRegex = RegExp(r"https?://[^\s\]\(\)]+"); final urlRegex = RegExp(r"https?://[^\s\]\(\)]+");
final theme = Theme.of(context); final theme = Theme.of(context);
return ref return ref
@ -98,7 +98,7 @@ class RoomChat extends HookConsumerWidget {
}) => showContextMenu( }) => showContextMenu(
context: context, context: context,
globalPosition: details.globalPosition, globalPosition: details.globalPosition,
onTap: () => replyToMessageId.value = message.id, onTap: () => replyToMessage.value = message,
), ),
onMessageLongPress: onMessageLongPress:
( (
@ -109,14 +109,73 @@ class RoomChat extends HookConsumerWidget {
}) => showContextMenu( }) => showContextMenu(
context: context, context: context,
globalPosition: details.globalPosition, globalPosition: details.globalPosition,
onTap: () => replyToMessageId.value = message.id, onTap: () => replyToMessage.value = message,
), ),
builders: Builders( builders: Builders(
composerBuilder: (_) => Composer( composerBuilder: (_) => Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (replyToMessage.value != null)
ColoredBox(
color: theme.colorScheme.surfaceContainer,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
child: Row(
spacing: 8,
children: [
Avatar(
userId: replyToMessage.value!.authorId,
headers: headers,
size: 16,
),
Text(
replyToMessage
.value!
.metadata?["displayName"] ??
replyToMessage.value!.authorId,
style: Theme.of(context)
.textTheme
.labelMedium
?.copyWith(
fontWeight: FontWeight.bold,
),
),
Expanded(
child: (replyToMessage.value as dynamic)
? Text(
(replyToMessage.value
as TextMessage)
.text,
overflow: TextOverflow.ellipsis,
style: Theme.of(
context,
).textTheme.labelMedium,
maxLines: 1,
)
: SizedBox(),
),
IconButton(
onPressed: () =>
replyToMessage.value = null,
icon: Icon(Icons.close),
iconSize: 20,
),
],
),
),
),
Composer(
sigmaX: 0,
sigmaY: 0,
sendIconColor: theme.colorScheme.primary, sendIconColor: theme.colorScheme.primary,
sendOnEnter: true, sendOnEnter: true,
autofocus: true, autofocus: true,
), ),
],
),
unsupportedMessageBuilder: unsupportedMessageBuilder:
( (
_, _,
@ -224,8 +283,8 @@ class RoomChat extends HookConsumerWidget {
onMessageSend: (message) { onMessageSend: (message) {
ref ref
.watch(controllerProvider.notifier) .watch(controllerProvider.notifier)
.send(message, replyTo: replyToMessageId.value); .send(message, replyTo: replyToMessage.value);
replyToMessageId.value = null; replyToMessage.value = null;
}, },
resolveUser: ref resolveUser: ref
.watch(controllerProvider.notifier) .watch(controllerProvider.notifier)