Autofocus chatbox on edit/reply
This commit is contained in:
parent
4aa962193d
commit
92f6b2fbba
3 changed files with 66 additions and 50 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter/services.dart";
|
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:fluttertagger/fluttertagger.dart";
|
import "package:fluttertagger/fluttertagger.dart";
|
||||||
|
|
@ -15,6 +14,7 @@ class ChatBox extends HookConsumerWidget {
|
||||||
final Message? relatedMessage;
|
final Message? relatedMessage;
|
||||||
final RelationType relationType;
|
final RelationType relationType;
|
||||||
final VoidCallback onDismiss;
|
final VoidCallback onDismiss;
|
||||||
|
final FocusNode? node;
|
||||||
final Future<void> Function(
|
final Future<void> Function(
|
||||||
String text, {
|
String text, {
|
||||||
required bool shouldMention,
|
required bool shouldMention,
|
||||||
|
|
@ -26,6 +26,7 @@ class ChatBox extends HookConsumerWidget {
|
||||||
required this.relationType,
|
required this.relationType,
|
||||||
required this.onDismiss,
|
required this.onDismiss,
|
||||||
required this.onSend,
|
required this.onSend,
|
||||||
|
this.node,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -55,18 +56,6 @@ class ChatBox extends HookConsumerWidget {
|
||||||
controller.value.text = "";
|
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(
|
final style = TextStyle(
|
||||||
color: theme.colorScheme.primary,
|
color: theme.colorScheme.primary,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
|
@ -135,7 +124,7 @@ class ChatBox extends HookConsumerWidget {
|
||||||
triggerCharacter: triggerCharacter.value,
|
triggerCharacter: triggerCharacter.value,
|
||||||
addTag: ({required id, required name}) {
|
addTag: ({required id, required name}) {
|
||||||
controller.value.addTag(id: id, name: name);
|
controller.value.addTag(id: id, name: name);
|
||||||
node.requestFocus();
|
node?.requestFocus();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
controller: controller.value,
|
controller: controller.value,
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ import "package:nexus/widgets/chat_page/room_menu.dart";
|
||||||
|
|
||||||
class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
||||||
final bool isDesktop;
|
final bool isDesktop;
|
||||||
final void Function(BuildContext context) onOpenMemberList;
|
final void Function(BuildContext context)? onOpenMemberList;
|
||||||
final void Function(BuildContext context) onOpenDrawer;
|
final void Function(BuildContext context) onOpenDrawer;
|
||||||
const RoomAppbar({
|
const RoomAppbar({
|
||||||
required this.isDesktop,
|
required this.isDesktop,
|
||||||
required this.onOpenMemberList,
|
|
||||||
required this.onOpenDrawer,
|
required this.onOpenDrawer,
|
||||||
|
this.onOpenMemberList,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -23,10 +23,12 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final room = ref.watch(SelectedRoomController.provider)!;
|
final room = ref.watch(SelectedRoomController.provider);
|
||||||
return Appbar(
|
return Appbar(
|
||||||
leading: isDesktop
|
leading: isDesktop
|
||||||
? ExpandableImage(
|
? room == null
|
||||||
|
? null
|
||||||
|
: ExpandableImage(
|
||||||
room.metadata?.avatar?.toString(),
|
room.metadata?.avatar?.toString(),
|
||||||
child: AvatarOrHash(
|
child: AvatarOrHash(
|
||||||
room.metadata?.avatar,
|
room.metadata?.avatar,
|
||||||
|
|
@ -37,7 +39,9 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
||||||
)
|
)
|
||||||
: DrawerButton(onPressed: () => onOpenDrawer(context)),
|
: DrawerButton(onPressed: () => onOpenDrawer(context)),
|
||||||
scrolledUnderElevation: 0,
|
scrolledUnderElevation: 0,
|
||||||
title: Column(
|
title: room == null
|
||||||
|
? null
|
||||||
|
: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -63,11 +67,11 @@ class RoomAppbar extends ConsumerWidget implements PreferredSizeWidget {
|
||||||
tooltip: "Open pinned messages",
|
tooltip: "Open pinned messages",
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => onOpenMemberList(context),
|
onPressed: () => onOpenMemberList?.call(context),
|
||||||
tooltip: "Open member list",
|
tooltip: "Open member list",
|
||||||
icon: Icon(Icons.people),
|
icon: Icon(Icons.people),
|
||||||
),
|
),
|
||||||
RoomMenu(room),
|
if (room != null) RoomMenu(room),
|
||||||
].toIList(),
|
].toIList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter/services.dart";
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:flutter_chat_ui/flutter_chat_ui.dart";
|
import "package:flutter_chat_ui/flutter_chat_ui.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
|
|
@ -47,17 +48,36 @@ class RoomChat extends HookConsumerWidget {
|
||||||
final danger = theme.colorScheme.error;
|
final danger = theme.colorScheme.error;
|
||||||
|
|
||||||
if (roomId == null || userId == null) {
|
if (roomId == null || userId == null) {
|
||||||
return Center(
|
return Scaffold(
|
||||||
|
appBar: RoomAppbar(
|
||||||
|
isDesktop: isDesktop,
|
||||||
|
onOpenDrawer: (_) => Scaffold.of(context).openDrawer(),
|
||||||
|
onOpenMemberList: null,
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
"Nothing to see here...",
|
"Nothing to see here...",
|
||||||
style: theme.textTheme.headlineMedium,
|
style: theme.textTheme.headlineMedium,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final controllerProvider = RoomChatController.provider(roomId);
|
final controllerProvider = RoomChatController.provider(roomId);
|
||||||
final notifier = ref.watch(controllerProvider.notifier);
|
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<PopupMenuEntry> getMessageOptions(Message message) {
|
List<PopupMenuEntry> getMessageOptions(Message message) {
|
||||||
final isSentByMe = message.authorId == userId;
|
final isSentByMe = message.authorId == userId;
|
||||||
return [
|
return [
|
||||||
|
|
@ -65,6 +85,7 @@ class RoomChat extends HookConsumerWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
relatedMessage.value = message;
|
relatedMessage.value = message;
|
||||||
relationType.value = RelationType.reply;
|
relationType.value = RelationType.reply;
|
||||||
|
composerNode.requestFocus();
|
||||||
},
|
},
|
||||||
child: ListTile(leading: Icon(Icons.reply), title: Text("Reply")),
|
child: ListTile(leading: Icon(Icons.reply), title: Text("Reply")),
|
||||||
),
|
),
|
||||||
|
|
@ -73,6 +94,7 @@ class RoomChat extends HookConsumerWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
relatedMessage.value = message;
|
relatedMessage.value = message;
|
||||||
relationType.value = RelationType.edit;
|
relationType.value = RelationType.edit;
|
||||||
|
composerNode.requestFocus();
|
||||||
},
|
},
|
||||||
child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")),
|
child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")),
|
||||||
),
|
),
|
||||||
|
|
@ -259,6 +281,7 @@ class RoomChat extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
|
|
||||||
composerBuilder: (_) => ChatBox(
|
composerBuilder: (_) => ChatBox(
|
||||||
|
node: composerNode,
|
||||||
onSend:
|
onSend:
|
||||||
(
|
(
|
||||||
text, {
|
text, {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue