Merge branch 'develop' into ISSUE-1456/SendingMessageIndicatorFix

This commit is contained in:
Sahil Kumar
2023-04-07 06:06:28 +05:30
committed by GitHub
4 changed files with 57 additions and 21 deletions
@@ -10,6 +10,7 @@
- Now it is possible to customize the max lines of the title of a url attachment. Before it was always 1 line. - Now it is possible to customize the max lines of the title of a url attachment. Before it was always 1 line.
- Added `attachmentActionsModalBuilder` parameter to `StreamMessageWidget` that allows to customize `AttachmentActionsModal`. - Added `attachmentActionsModalBuilder` parameter to `StreamMessageWidget` that allows to customize `AttachmentActionsModal`.
- Added `StreamMessageInput.sendMessageKeyPredicate` and `StreamMessageInput.clearQuotedMessageKeyPredicate` to customize the keys used to send and clear the quoted message.
🔄 Changed 🔄 Changed
@@ -1,4 +1,4 @@
import 'package:flutter/material.dart' show Theme; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
/// A generic widget builder function. /// A generic widget builder function.
@@ -30,7 +30,7 @@ abstract class PlatformWidgetBase<M extends Widget, D extends Widget,
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final platform = Theme.of(context).platform; final platform = defaultTargetPlatform;
if (platform == TargetPlatform.android || platform == TargetPlatform.iOS) { if (platform == TargetPlatform.android || platform == TargetPlatform.iOS) {
return createMobileWidget(context); return createMobileWidget(context);
} else if (platform == TargetPlatform.macOS || } else if (platform == TargetPlatform.macOS ||
@@ -7,6 +7,7 @@ import 'package:cached_network_image/cached_network_image.dart'
hide ErrorListener; hide ErrorListener;
import 'package:desktop_drop/desktop_drop.dart'; import 'package:desktop_drop/desktop_drop.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:photo_manager/photo_manager.dart'; import 'package:photo_manager/photo_manager.dart';
import 'package:shimmer/shimmer.dart'; import 'package:shimmer/shimmer.dart';
@@ -110,8 +111,17 @@ class StreamMessageInput extends StatefulWidget {
this.enableMentionsOverlay = true, this.enableMentionsOverlay = true,
this.onQuotedMessageCleared, this.onQuotedMessageCleared,
this.enableActionAnimation = true, this.enableActionAnimation = true,
this.sendMessageKeyPredicate = _defaultSendMessageKeyPredicate,
this.clearQuotedMessageKeyPredicate =
_defaultClearQuotedMessageKeyPredicate,
}); });
/// The predicate used to send a message on desktop/web
final KeyEventPredicate sendMessageKeyPredicate;
/// The predicate used to clear the quoted message on desktop/web
final KeyEventPredicate 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;
@@ -252,6 +262,22 @@ 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,
KeyEvent event,
) {
// On desktop/web, send the message when the user presses the enter key.
return event is KeyUpEvent && event.logicalKey == LogicalKeyboardKey.enter;
}
static bool _defaultClearQuotedMessageKeyPredicate(
FocusNode node,
KeyEvent event,
) {
// On desktop/web, clear the quoted message when the user presses the escape key.
return event is KeyUpEvent && event.logicalKey == LogicalKeyboardKey.escape;
}
@override @override
StreamMessageInputState createState() => StreamMessageInputState(); StreamMessageInputState createState() => StreamMessageInputState();
} }
@@ -509,9 +535,6 @@ class StreamMessageInputState extends State<StreamMessageInput>
: CrossFadeState.showSecond, : CrossFadeState.showSecond,
), ),
), ),
// PlatformWidgetBuilder(
// mobile: (context, child) => _buildFilePickerSection(),
// ),
], ],
), ),
), ),
@@ -753,24 +776,12 @@ class StreamMessageInputState extends State<StreamMessageInput>
LimitedBox( LimitedBox(
maxHeight: widget.maxHeight, maxHeight: widget.maxHeight,
child: PlatformWidgetBuilder( child: PlatformWidgetBuilder(
web: (context, child) => KeyboardShortcutRunner( web: (context, child) => Focus(
onEnterKeypress: sendMessage, onKeyEvent: _handleKeyPressed,
onEscapeKeypress: () {
if (_hasQuotedMessage &&
_effectiveController.text.isEmpty) {
widget.onQuotedMessageCleared?.call();
}
},
child: child!, child: child!,
), ),
desktop: (context, child) => KeyboardShortcutRunner( desktop: (context, child) => Focus(
onEnterKeypress: sendMessage, onKeyEvent: _handleKeyPressed,
onEscapeKeypress: () {
if (_hasQuotedMessage &&
_effectiveController.text.isEmpty) {
widget.onQuotedMessageCleared?.call();
}
},
child: child!, child: child!,
), ),
mobile: (context, child) => child, mobile: (context, child) => child,
@@ -801,6 +812,25 @@ class StreamMessageInputState extends State<StreamMessageInput>
); );
} }
KeyEventResult _handleKeyPressed(FocusNode node, KeyEvent event) {
// Check for send message key.
if (widget.sendMessageKeyPredicate(node, event)) {
sendMessage();
return KeyEventResult.handled;
}
// Check for clear quoted message key.
if (widget.clearQuotedMessageKeyPredicate(node, event)) {
if (_hasQuotedMessage && _effectiveController.text.isEmpty) {
widget.onQuotedMessageCleared?.call();
}
return KeyEventResult.handled;
}
// Return ignored to allow other key events to be 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 key event
/// {@endtemplate}
typedef KeyEventPredicate = bool Function(FocusNode, KeyEvent);
/// {@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}