fix(ui): use a predicate instead of a key

This commit is contained in:
Salvatore Giordano
2022-10-31 12:22:56 +01:00
parent d814d5b0a3
commit 64e41475d9
3 changed files with 46 additions and 41 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
✅ Added ✅ Added
- Added `StreamMessageInput.sendMessageKey` and `StreamMessageInput.clearQuotedMessageKey` to customize the keys used to send and clear the quoted message. - Added `StreamMessageInput.sendMessageKeyPredicate` and `StreamMessageInput.clearQuotedMessageKeyPredicate` to customize the keys used to send and clear the quoted message.
## 5.1.0 ## 5.1.0
@@ -111,15 +111,16 @@ class StreamMessageInput extends StatefulWidget {
this.enableMentionsOverlay = true, this.enableMentionsOverlay = true,
this.onQuotedMessageCleared, this.onQuotedMessageCleared,
this.enableActionAnimation = true, this.enableActionAnimation = true,
this.sendMessageKey = PhysicalKeyboardKey.enter, this.sendMessageKeyPredicate = _defaultSendMessageKeyPredicate,
this.clearQuotedMessageKey = PhysicalKeyboardKey.escape, this.clearQuotedMessageKeyPredicate =
_defaultClearQuotedMessageKeyPredicate,
}); });
/// The key used to send a message on web/desktop /// The predicate used to send a message on desktop/web
final PhysicalKeyboardKey? sendMessageKey; final RawKeyEventPredicate? sendMessageKeyPredicate;
/// The key used to send a message on web/desktop /// The predicate used to clear the quoted message on desktop/web
final PhysicalKeyboardKey? clearQuotedMessageKey; final RawKeyEventPredicate? clearQuotedMessageKeyPredicate;
/// If true the message input will animate the actions while you type /// If true the message input will animate the actions while you type
final bool enableActionAnimation; final bool enableActionAnimation;
@@ -261,6 +262,18 @@ class StreamMessageInput extends StatefulWidget {
static bool _defaultValidator(Message message) => static bool _defaultValidator(Message message) =>
message.text?.isNotEmpty == true || message.attachments.isNotEmpty; message.text?.isNotEmpty == true || message.attachments.isNotEmpty;
static bool _defaultSendMessageKeyPredicate(
FocusNode node,
RawKeyEvent event,
) =>
event.logicalKey == LogicalKeyboardKey.enter;
static bool _defaultClearQuotedMessageKeyPredicate(
FocusNode node,
RawKeyEvent event,
) =>
event.logicalKey == LogicalKeyboardKey.escape;
@override @override
StreamMessageInputState createState() => StreamMessageInputState(); StreamMessageInputState createState() => StreamMessageInputState();
} }
@@ -760,44 +773,12 @@ class StreamMessageInputState extends State<StreamMessageInput>
maxHeight: widget.maxHeight, maxHeight: widget.maxHeight,
child: PlatformWidgetBuilder( child: PlatformWidgetBuilder(
web: (context, child) => Focus( web: (context, child) => Focus(
onKey: _handleKeyPressed,
child: child!, child: child!,
onKeyEvent: (node, event) {
if (widget.sendMessageKey != null &&
event.physicalKey == widget.sendMessageKey) {
sendMessage();
return KeyEventResult.handled;
} else if (widget.clearQuotedMessageKey != null &&
event.physicalKey ==
widget.clearQuotedMessageKey) {
if (_hasQuotedMessage &&
_effectiveController.text.isEmpty) {
widget.onQuotedMessageCleared?.call();
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
), ),
desktop: (context, child) => Focus( desktop: (context, child) => Focus(
onKey: _handleKeyPressed,
child: child!, child: child!,
onKeyEvent: (node, event) {
if (widget.sendMessageKey != null &&
event.physicalKey == widget.sendMessageKey) {
sendMessage();
return KeyEventResult.handled;
} else if (widget.clearQuotedMessageKey != null &&
event.physicalKey ==
widget.clearQuotedMessageKey) {
if (_hasQuotedMessage &&
_effectiveController.text.isEmpty) {
widget.onQuotedMessageCleared?.call();
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
), ),
mobile: (context, child) => child, mobile: (context, child) => child,
child: StreamMessageTextField( child: StreamMessageTextField(
@@ -827,6 +808,25 @@ class StreamMessageInputState extends State<StreamMessageInput>
); );
} }
KeyEventResult _handleKeyPressed(
FocusNode node,
RawKeyEvent event,
) {
if (widget.sendMessageKeyPredicate != null &&
widget.sendMessageKeyPredicate!(node, event)) {
sendMessage();
return KeyEventResult.handled;
} else if (widget.clearQuotedMessageKeyPredicate != null &&
widget.clearQuotedMessageKeyPredicate!(node, event)) {
if (_hasQuotedMessage && _effectiveController.text.isEmpty) {
widget.onQuotedMessageCleared?.call();
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
}
InputDecoration _getInputDecoration(BuildContext context) { InputDecoration _getInputDecoration(BuildContext context) {
final passedDecoration = _messageInputTheme.inputDecoration; final passedDecoration = _messageInputTheme.inputDecoration;
return InputDecoration( return InputDecoration(
@@ -340,6 +340,11 @@ typedef DownloadedPathCallback = void Function(String? path);
/// {@endtemplate} /// {@endtemplate}
typedef UserTapCallback = void Function(User, Widget?); typedef UserTapCallback = void Function(User, Widget?);
/// {@template rawKeyEventPredicate}
/// Callback called to react to a raw key event
/// {@endtemplate}
typedef RawKeyEventPredicate = bool Function(FocusNode, RawKeyEvent);
/// {@template userItemBuilder} /// {@template userItemBuilder}
/// Builder used to create a custom [ListUserItem] from a [User] /// Builder used to create a custom [ListUserItem] from a [User]
/// {@endtemplate} /// {@endtemplate}