Merge pull request #821 from GetStream/chore/message-input-controller-review
chore(ui, core): docs and linting improvements
This commit is contained in:
@@ -4,7 +4,6 @@ import 'dart:math';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@@ -14,16 +13,12 @@ import 'package:stream_chat_flutter/src/commands_overlay.dart';
|
||||
import 'package:stream_chat_flutter/src/emoji/emoji.dart';
|
||||
import 'package:stream_chat_flutter/src/emoji_overlay.dart';
|
||||
import 'package:stream_chat_flutter/src/extension.dart';
|
||||
import 'package:stream_chat_flutter/src/message_list_view.dart';
|
||||
import 'package:stream_chat_flutter/src/multi_overlay.dart';
|
||||
import 'package:stream_chat_flutter/src/quoted_message_widget.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
||||
import 'package:stream_chat_flutter/src/user_mentions_overlay.dart';
|
||||
import 'package:stream_chat_flutter/src/video_service.dart';
|
||||
import 'package:stream_chat_flutter/src/video_thumbnail_image.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
import 'package:video_compress/video_compress.dart';
|
||||
|
||||
export 'package:video_compress/video_compress.dart' show VideoQuality;
|
||||
@@ -42,13 +37,14 @@ typedef ErrorListener = void Function(
|
||||
///
|
||||
/// This callback should not throw.
|
||||
///
|
||||
/// It exists merely for showing custom error, and should not be used otherwise.
|
||||
/// It exists merely for showing a custom error, and should not be used
|
||||
/// otherwise.
|
||||
typedef AttachmentLimitExceedListener = void Function(
|
||||
int limit,
|
||||
String error,
|
||||
);
|
||||
|
||||
/// Builder for attachment thumbnails
|
||||
/// Builder for attachment thumbnails.
|
||||
typedef AttachmentThumbnailBuilder = Widget Function(
|
||||
BuildContext,
|
||||
Attachment,
|
||||
@@ -77,8 +73,8 @@ typedef ActionButtonBuilder = Widget Function(
|
||||
IconButton defaultActionButton,
|
||||
);
|
||||
|
||||
/// Widget builder for widgets that require may required data from the
|
||||
/// [MessageInputController]
|
||||
/// Widget builder for widgets that may require data from the
|
||||
/// [MessageInputController].
|
||||
typedef MessageRelatedBuilder = Widget Function(
|
||||
BuildContext context,
|
||||
MessageInputController messageInputController,
|
||||
@@ -91,7 +87,7 @@ typedef AttachmentsPickerBuilder = Widget Function(
|
||||
StreamAttachmentPicker defaultPicker,
|
||||
);
|
||||
|
||||
/// Location for actions on the [MessageInput]
|
||||
/// Location for actions on the [MessageInput].
|
||||
enum ActionsLocation {
|
||||
/// Align to left
|
||||
left,
|
||||
@@ -106,7 +102,7 @@ enum ActionsLocation {
|
||||
rightInside,
|
||||
}
|
||||
|
||||
/// Default attachments for widget
|
||||
/// Default attachments for widget.
|
||||
enum DefaultAttachmentTypes {
|
||||
/// Image Attachment
|
||||
image,
|
||||
@@ -118,7 +114,7 @@ enum DefaultAttachmentTypes {
|
||||
file,
|
||||
}
|
||||
|
||||
/// Available locations for the sendMessage button relative to the textField
|
||||
/// Available locations for the `sendMessage` button relative to the textField.
|
||||
enum SendButtonLocation {
|
||||
/// inside the textField
|
||||
inside,
|
||||
@@ -131,17 +127,17 @@ const _kMinMediaPickerSize = 360.0;
|
||||
|
||||
const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
||||
|
||||
/// Inactive state
|
||||
/// Inactive state:
|
||||
///
|
||||
/// 
|
||||
/// 
|
||||
///
|
||||
/// Focused state
|
||||
/// Focused state:
|
||||
///
|
||||
/// 
|
||||
/// 
|
||||
///
|
||||
/// Widget used to enter the message and add attachments
|
||||
/// Widget used to enter a message and add attachments:
|
||||
///
|
||||
/// ```dart
|
||||
/// class ChannelPage extends StatelessWidget {
|
||||
@@ -176,8 +172,7 @@ const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
||||
/// as the bottom widget.
|
||||
///
|
||||
/// The widget renders the ui based on the first ancestor of
|
||||
/// type [StreamChatTheme].
|
||||
/// Modify it to change the widget appearance.
|
||||
/// type [StreamChatTheme]. Modify it to change the widget appearance.
|
||||
class MessageInput extends StatefulWidget {
|
||||
/// Instantiate a new MessageInput
|
||||
const MessageInput({
|
||||
@@ -218,61 +213,60 @@ class MessageInput extends StatefulWidget {
|
||||
this.shouldKeepFocusAfterMessage,
|
||||
}) : super(key: key);
|
||||
|
||||
/// List of options for showing overlays
|
||||
/// List of options for showing overlays.
|
||||
final List<OverlayOptions> customOverlays;
|
||||
|
||||
/// Video quality to use when compressing the videos
|
||||
/// Video quality to use when compressing the videos.
|
||||
final VideoQuality compressedVideoQuality;
|
||||
|
||||
/// Frame rate to use when compressing the videos
|
||||
/// Frame rate to use when compressing the videos.
|
||||
final int compressedVideoFrameRate;
|
||||
|
||||
/// Max attachment size in bytes
|
||||
/// Defaults to 20 MB
|
||||
/// do not set it if you're using our default CDN
|
||||
/// Max attachment size in bytes:
|
||||
/// - Defaults to 20 MB
|
||||
/// - Do not set it if you're using our default CDN
|
||||
final int maxAttachmentSize;
|
||||
|
||||
/// Function called after sending the message
|
||||
/// Function called after sending the message.
|
||||
final void Function(Message)? onMessageSent;
|
||||
|
||||
/// Function called right before sending the message
|
||||
/// Use this to transform the message
|
||||
/// Function called right before sending the message.
|
||||
///
|
||||
/// Use this to transform the message.
|
||||
final FutureOr<Message> Function(Message)? preMessageSending;
|
||||
|
||||
/// Maximum Height for the TextField to grow before it starts scrolling
|
||||
/// Maximum Height for the TextField to grow before it starts scrolling.
|
||||
final double maxHeight;
|
||||
|
||||
/// The keyboard type assigned to the TextField
|
||||
/// The keyboard type assigned to the TextField.
|
||||
final TextInputType keyboardType;
|
||||
|
||||
/// If true the attachments button will not be displayed
|
||||
/// If true the attachments button will not be displayed.
|
||||
final bool disableAttachments;
|
||||
|
||||
/// Use this property to hide/show the commands button
|
||||
/// Use this property to hide/show the commands button.
|
||||
final bool showCommandsButton;
|
||||
|
||||
/// Hide send as dm checkbox
|
||||
/// Hide send as dm checkbox.
|
||||
final bool hideSendAsDm;
|
||||
|
||||
/// The text controller of the TextField
|
||||
/// The text controller of the TextField.
|
||||
final MessageInputController? messageInputController;
|
||||
|
||||
/// List of action widgets
|
||||
/// List of action widgets.
|
||||
final List<Widget> actions;
|
||||
|
||||
/// The location of the custom actions
|
||||
/// The location of the custom actions.
|
||||
final ActionsLocation actionsLocation;
|
||||
|
||||
/// Map that defines a thumbnail builder for an attachment type
|
||||
/// Map that defines a thumbnail builder for an attachment type.
|
||||
final Map<String, AttachmentThumbnailBuilder>? attachmentThumbnailBuilders;
|
||||
|
||||
/// The focus node associated to the TextField
|
||||
/// The focus node associated to the TextField.
|
||||
final FocusNode? focusNode;
|
||||
|
||||
///
|
||||
final Message? quotedMessage;
|
||||
|
||||
///
|
||||
final VoidCallback? onQuotedMessageCleared;
|
||||
|
||||
/// The location of the send button
|
||||
|
||||
@@ -21,7 +21,6 @@ typedef CustomAttachmentIconBuilder = Widget Function(
|
||||
bool active,
|
||||
);
|
||||
|
||||
///
|
||||
class StreamAttachmentPicker extends StatefulWidget {
|
||||
final bool isOpen;
|
||||
final double pickerSize;
|
||||
@@ -32,15 +31,15 @@ class StreamAttachmentPicker extends StatefulWidget {
|
||||
final ValueChanged<String>? onError;
|
||||
final FilePickerCallback onFilePicked;
|
||||
|
||||
/// Video quality to use when compressing the videos
|
||||
/// Video quality to use when compressing the videos.
|
||||
final VideoQuality compressedVideoQuality;
|
||||
|
||||
/// Frame rate to use when compressing the videos
|
||||
/// Frame rate to use when compressing the videos.
|
||||
final int compressedVideoFrameRate;
|
||||
|
||||
/// Max attachment size in bytes
|
||||
/// Defaults to 20 MB
|
||||
/// do not set it if you're using our default CDN
|
||||
/// Max attachment size in bytes:
|
||||
/// - Defaults to 20 MB
|
||||
/// - Do not set it if you're using our default CDN
|
||||
final int maxAttachmentSize;
|
||||
|
||||
final List<DefaultAttachmentTypes> allowedAttachmentTypes;
|
||||
|
||||
@@ -21,8 +21,8 @@ export 'package:flutter/services.dart'
|
||||
class StreamMessageTextField extends StatefulWidget {
|
||||
/// Creates a Material Design text field.
|
||||
///
|
||||
/// If [decoration] is non-null (which is the default), the text field requires
|
||||
/// one of its ancestors to be a [Material] widget.
|
||||
/// If [decoration] is non-null (which is the default), the text field
|
||||
/// requires one of its ancestors to be a [Material] widget.
|
||||
///
|
||||
/// To remove the decoration entirely (including the extra padding introduced
|
||||
/// by the decoration to save space for the labels), set the [decoration] to
|
||||
@@ -115,7 +115,7 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
|
||||
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
|
||||
this.keyboardAppearance,
|
||||
this.scrollPadding = const EdgeInsets.all(20.0),
|
||||
this.scrollPadding = const EdgeInsets.all(20),
|
||||
this.dragStartBehavior = DragStartBehavior.start,
|
||||
this.enableInteractiveSelection = true,
|
||||
this.selectionControls,
|
||||
@@ -127,34 +127,24 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
this.autofillHints,
|
||||
this.restorationId,
|
||||
this.enableIMEPersonalizedLearning = true,
|
||||
}) : assert(textAlign != null),
|
||||
assert(readOnly != null),
|
||||
assert(autofocus != null),
|
||||
assert(obscuringCharacter != null && obscuringCharacter.length == 1),
|
||||
assert(obscureText != null),
|
||||
assert(autocorrect != null),
|
||||
}) : assert(obscuringCharacter.length == 1,
|
||||
'`obscuringCharacter.length` must be 1'),
|
||||
smartDashesType = smartDashesType ??
|
||||
(obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
|
||||
smartQuotesType = smartQuotesType ??
|
||||
(obscureText ? SmartQuotesType.disabled : SmartQuotesType.enabled),
|
||||
assert(enableSuggestions != null),
|
||||
assert(enableInteractiveSelection != null),
|
||||
assert(maxLengthEnforced != null),
|
||||
assert(
|
||||
maxLengthEnforced || maxLengthEnforcement == null,
|
||||
'maxLengthEnforced is deprecated, use only maxLengthEnforcement',
|
||||
),
|
||||
assert(scrollPadding != null),
|
||||
assert(dragStartBehavior != null),
|
||||
assert(selectionHeightStyle != null),
|
||||
assert(selectionWidthStyle != null),
|
||||
assert(maxLines == null || maxLines > 0),
|
||||
assert(minLines == null || minLines > 0),
|
||||
assert(maxLines == null || maxLines > 0,
|
||||
'`maxLines` needs to be left as null or bigger than 0'),
|
||||
assert(minLines == null || minLines > 0,
|
||||
'`minLines` needs to be left as null or bigger than 0'),
|
||||
assert(
|
||||
(maxLines == null) || (minLines == null) || (maxLines >= minLines),
|
||||
"minLines can't be greater than maxLines",
|
||||
),
|
||||
assert(expands != null),
|
||||
assert(
|
||||
!expands || (maxLines == null && minLines == null),
|
||||
'minLines and maxLines must be null when expands is true.',
|
||||
@@ -164,14 +154,15 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
assert(maxLength == null ||
|
||||
maxLength == TextField.noMaxLength ||
|
||||
maxLength > 0),
|
||||
// Assert the following instead of setting it directly to avoid surprising the user by silently changing the value they set.
|
||||
|
||||
// Assert the following instead of setting it directly to avoid
|
||||
// surprising the user by silently changing the value they set.
|
||||
assert(
|
||||
!identical(textInputAction, TextInputAction.newline) ||
|
||||
maxLines == 1 ||
|
||||
!identical(keyboardType, TextInputType.text),
|
||||
'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.',
|
||||
'''Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.''',
|
||||
),
|
||||
assert(enableIMEPersonalizedLearning != null),
|
||||
keyboardType = keyboardType ??
|
||||
(maxLines == 1 ? TextInputType.text : TextInputType.multiline),
|
||||
toolbarOptions = toolbarOptions ??
|
||||
@@ -230,7 +221,8 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
/// cause the focus to change, and will not make the keyboard visible.
|
||||
///
|
||||
/// This widget builds an [EditableText] and will ensure that the keyboard is
|
||||
/// showing when it is tapped by calling [EditableTextState.requestKeyboard()].
|
||||
/// showing when it is tapped by calling
|
||||
/// [EditableTextState.requestKeyboard()].
|
||||
final FocusNode? focusNode;
|
||||
|
||||
/// The decoration to show around the text field.
|
||||
@@ -330,16 +322,20 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
/// If set, a character counter will be displayed below the
|
||||
/// field showing how many characters have been entered. If set to a number
|
||||
/// greater than 0, it will also display the maximum number allowed. If set
|
||||
/// to [TextField.noMaxLength] then only the current character count is displayed.
|
||||
/// to [TextField.noMaxLength] then only the current character count is
|
||||
/// displayed.
|
||||
///
|
||||
/// After [maxLength] characters have been input, additional input
|
||||
/// is ignored, unless [maxLengthEnforcement] is set to
|
||||
/// [MaxLengthEnforcement.none].
|
||||
///
|
||||
/// The text field enforces the length with a [LengthLimitingTextInputFormatter],
|
||||
/// which is evaluated after the supplied [inputFormatters], if any.
|
||||
/// The text field enforces the length with a
|
||||
/// [LengthLimitingTextInputFormatter], which is evaluated after the supplied
|
||||
/// [inputFormatters], if any.
|
||||
///
|
||||
/// This value must be either null, [TextField.noMaxLength], or greater than
|
||||
/// 0.
|
||||
///
|
||||
/// This value must be either null, [TextField.noMaxLength], or greater than 0.
|
||||
/// If null (the default) then there is no limit to the number of characters
|
||||
/// that can be entered. If set to [TextField.noMaxLength], then no limit will
|
||||
/// be enforced, but the number of characters entered will still be displayed.
|
||||
@@ -446,7 +442,8 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
///
|
||||
/// This setting is only honored on iOS devices.
|
||||
///
|
||||
/// If unset, defaults to the brightness of [ThemeData.primaryColorBrightness].
|
||||
/// If unset, defaults to the brightness of
|
||||
/// [ThemeData.primaryColorBrightness].
|
||||
final Brightness? keyboardAppearance;
|
||||
|
||||
/// {@macro flutter.widgets.editableText.scrollPadding}
|
||||
@@ -490,14 +487,16 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
/// widget.
|
||||
///
|
||||
/// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
|
||||
/// [MaterialStateProperty.resolve] is used for the following [MaterialState]s:
|
||||
/// [MaterialStateProperty.resolve] is used for the following
|
||||
/// [MaterialState]s:
|
||||
///
|
||||
/// * [MaterialState.error].
|
||||
/// * [MaterialState.hovered].
|
||||
/// * [MaterialState.focused].
|
||||
/// * [MaterialState.disabled].
|
||||
///
|
||||
/// If this property is null, [MaterialStateMouseCursor.textable] will be used.
|
||||
/// If this property is null, [MaterialStateMouseCursor.textable] will be
|
||||
/// used.
|
||||
///
|
||||
/// The [mouseCursor] is the only property of [TextField] that controls the
|
||||
/// appearance of the mouse pointer. All other properties related to "cursor"
|
||||
|
||||
Reference in New Issue
Block a user