diff --git a/lib/widgets/chat_page/composer/chat_box.dart b/lib/widgets/chat_page/composer/chat_box.dart index 894dbfa..41bc123 100644 --- a/lib/widgets/chat_page/composer/chat_box.dart +++ b/lib/widgets/chat_page/composer/chat_box.dart @@ -1,6 +1,5 @@ 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"; @@ -15,6 +14,7 @@ class ChatBox extends HookConsumerWidget { final Message? relatedMessage; final RelationType relationType; final VoidCallback onDismiss; + final FocusNode? node; final Future Function( String text, { required bool shouldMention, @@ -26,6 +26,7 @@ class ChatBox extends HookConsumerWidget { required this.relationType, required this.onDismiss, required this.onSend, + this.node, super.key, }); @@ -55,18 +56,6 @@ class ChatBox extends HookConsumerWidget { controller.value.text = ""; } - final node = useFocusNode( - onKeyEvent: (_, event) { - if (event is KeyDownEvent && - event.logicalKey == LogicalKeyboardKey.escape) { - onDismiss(); - return KeyEventResult.handled; - } - - return KeyEventResult.ignored; - }, - ); - final style = TextStyle( color: theme.colorScheme.primary, fontWeight: FontWeight.bold, @@ -135,7 +124,7 @@ class ChatBox extends HookConsumerWidget { triggerCharacter: triggerCharacter.value, addTag: ({required id, required name}) { controller.value.addTag(id: id, name: name); - node.requestFocus(); + node?.requestFocus(); }, ), controller: controller.value, diff --git a/lib/widgets/chat_page/room_appbar.dart b/lib/widgets/chat_page/room_appbar.dart index 3df7f9d..62e282d 100644 --- a/lib/widgets/chat_page/room_appbar.dart +++ b/lib/widgets/chat_page/room_appbar.dart @@ -9,12 +9,12 @@ import "package:nexus/widgets/chat_page/room_menu.dart"; class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget { final bool isDesktop; - final void Function(BuildContext context) onOpenMemberList; + final void Function(BuildContext context)? onOpenMemberList; final void Function(BuildContext context) onOpenDrawer; const RoomAppbar({ required this.isDesktop, - required this.onOpenMemberList, required this.onOpenDrawer, + this.onOpenMemberList, super.key, }); @@ -23,39 +23,43 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final room = ref.watch(SelectedRoomController.provider)!; + 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), - ), - ) + ? room == null + ? null + : 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) - Text( - room.metadata!.topic!, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.labelMedium?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), + title: room == null + ? null + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + room.metadata?.name ?? "Unnamed Room", + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + 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, + ), + ), + ], ), - ], - ), actions: [ IconButton( onPressed: null, @@ -63,11 +67,11 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget { tooltip: "Open pinned messages", ), IconButton( - onPressed: () => onOpenMemberList(context), + onPressed: () => onOpenMemberList?.call(context), tooltip: "Open member list", icon: Icon(Icons.people), ), - RoomMenu(room), + if (room != null) RoomMenu(room), ].toIList(), ); } diff --git a/lib/widgets/chat_page/room_chat.dart b/lib/widgets/chat_page/room_chat.dart index d85c826..9c950e9 100644 --- a/lib/widgets/chat_page/room_chat.dart +++ b/lib/widgets/chat_page/room_chat.dart @@ -1,4 +1,5 @@ import "package:flutter/material.dart"; +import "package:flutter/services.dart"; import "package:flutter_chat_core/flutter_chat_core.dart"; import "package:flutter_chat_ui/flutter_chat_ui.dart"; import "package:flutter_hooks/flutter_hooks.dart"; @@ -47,10 +48,17 @@ class RoomChat extends HookConsumerWidget { final danger = theme.colorScheme.error; if (roomId == null || userId == null) { - return Center( - child: Text( - "Nothing to see here...", - style: theme.textTheme.headlineMedium, + return Scaffold( + appBar: RoomAppbar( + isDesktop: isDesktop, + onOpenDrawer: (_) => Scaffold.of(context).openDrawer(), + onOpenMemberList: null, + ), + body: Center( + child: Text( + "Nothing to see here...", + style: theme.textTheme.headlineMedium, + ), ), ); } @@ -58,6 +66,18 @@ class RoomChat extends HookConsumerWidget { final controllerProvider = RoomChatController.provider(roomId); final notifier = ref.watch(controllerProvider.notifier); + final composerNode = useFocusNode( + onKeyEvent: (_, event) { + if (event is KeyDownEvent && + event.logicalKey == LogicalKeyboardKey.escape) { + relatedMessage.value = null; + return KeyEventResult.handled; + } + + return KeyEventResult.ignored; + }, + ); + List getMessageOptions(Message message) { final isSentByMe = message.authorId == userId; return [ @@ -65,6 +85,7 @@ class RoomChat extends HookConsumerWidget { onTap: () { relatedMessage.value = message; relationType.value = RelationType.reply; + composerNode.requestFocus(); }, child: ListTile(leading: Icon(Icons.reply), title: Text("Reply")), ), @@ -73,6 +94,7 @@ class RoomChat extends HookConsumerWidget { onTap: () { relatedMessage.value = message; relationType.value = RelationType.edit; + composerNode.requestFocus(); }, child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")), ), @@ -259,6 +281,7 @@ class RoomChat extends HookConsumerWidget { ), composerBuilder: (_) => ChatBox( + node: composerNode, onSend: ( text, {