Merge pull request #821 from GetStream/chore/message-input-controller-review
chore(ui, core): docs and linting improvements
This commit is contained in:
@@ -1,18 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:logging/logging.dart';
|
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
import 'package:stream_chat/src/client/channel.dart';
|
|
||||||
import 'package:stream_chat/src/client/retry_policy.dart';
|
import 'package:stream_chat/src/client/retry_policy.dart';
|
||||||
import 'package:stream_chat/src/core/error/error.dart';
|
|
||||||
import 'package:stream_chat/src/core/models/message.dart';
|
|
||||||
import 'package:stream_chat/src/event_type.dart';
|
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
|
||||||
/// The retry queue associated to a channel
|
/// The retry queue associated to a channel.
|
||||||
class RetryQueue {
|
class RetryQueue {
|
||||||
/// Instantiate a new RetryQueue object
|
/// Instantiate a new RetryQueue object.
|
||||||
RetryQueue({
|
RetryQueue({
|
||||||
required this.channel,
|
required this.channel,
|
||||||
this.logger,
|
this.logger,
|
||||||
@@ -22,13 +17,13 @@ class RetryQueue {
|
|||||||
_listenFailedEvents();
|
_listenFailedEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The channel of this queue
|
/// The channel of this queue.
|
||||||
final Channel channel;
|
final Channel channel;
|
||||||
|
|
||||||
/// The client associated with this [channel]
|
/// The client associated with this [channel].
|
||||||
final StreamChatClient client;
|
final StreamChatClient client;
|
||||||
|
|
||||||
/// The logger associated to this queue
|
/// The logger associated to this queue.
|
||||||
final Logger? logger;
|
final Logger? logger;
|
||||||
|
|
||||||
late final RetryPolicy _retryPolicy;
|
late final RetryPolicy _retryPolicy;
|
||||||
@@ -68,7 +63,7 @@ class RetryQueue {
|
|||||||
}).addTo(_compositeSubscription);
|
}).addTo(_compositeSubscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a list of messages
|
/// Add a list of messages.
|
||||||
void add(List<Message> messages) {
|
void add(List<Message> messages) {
|
||||||
if (messages.isEmpty) return;
|
if (messages.isEmpty) return;
|
||||||
if (!_messageQueue.containsAllMessage(messages)) {
|
if (!_messageQueue.containsAllMessage(messages)) {
|
||||||
@@ -180,10 +175,10 @@ class RetryQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether our [_messageQueue] has messages or not
|
/// Whether our [_messageQueue] has messages or not.
|
||||||
bool get hasMessages => _messageQueue.isNotEmpty;
|
bool get hasMessages => _messageQueue.isNotEmpty;
|
||||||
|
|
||||||
/// Call this method to dispose this object
|
/// Call this method to dispose this object.
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_messageQueue.clear();
|
_messageQueue.clear();
|
||||||
_compositeSubscription.dispose();
|
_compositeSubscription.dispose();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class _PinExpires {
|
|||||||
|
|
||||||
const _pinExpires = _PinExpires();
|
const _pinExpires = _PinExpires();
|
||||||
|
|
||||||
/// Enum defining the status of a sending message
|
/// Enum defining the status of a sending message.
|
||||||
enum MessageSendingStatus {
|
enum MessageSendingStatus {
|
||||||
/// Message is being sent
|
/// Message is being sent
|
||||||
sending,
|
sending,
|
||||||
@@ -40,10 +40,10 @@ enum MessageSendingStatus {
|
|||||||
sent,
|
sent,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The class that contains the information about a message
|
/// The class that contains the information about a message.
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class Message extends Equatable {
|
class Message extends Equatable {
|
||||||
/// Constructor used for json serialization
|
/// Constructor used for json serialization.
|
||||||
Message({
|
Message({
|
||||||
String? id,
|
String? id,
|
||||||
this.text,
|
this.text,
|
||||||
@@ -65,13 +65,13 @@ class Message extends Equatable {
|
|||||||
this.command,
|
this.command,
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
DateTime? updatedAt,
|
DateTime? updatedAt,
|
||||||
|
this.deletedAt,
|
||||||
this.user,
|
this.user,
|
||||||
this.pinned = false,
|
this.pinned = false,
|
||||||
this.pinnedAt,
|
this.pinnedAt,
|
||||||
DateTime? pinExpires,
|
DateTime? pinExpires,
|
||||||
this.pinnedBy,
|
this.pinnedBy,
|
||||||
this.extraData = const {},
|
this.extraData = const {},
|
||||||
this.deletedAt,
|
|
||||||
this.status = MessageSendingStatus.sending,
|
this.status = MessageSendingStatus.sending,
|
||||||
this.i18n,
|
this.i18n,
|
||||||
}) : id = id ?? const Uuid().v4(),
|
}) : id = id ?? const Uuid().v4(),
|
||||||
@@ -80,7 +80,7 @@ class Message extends Equatable {
|
|||||||
_updatedAt = updatedAt,
|
_updatedAt = updatedAt,
|
||||||
_quotedMessageId = quotedMessageId;
|
_quotedMessageId = quotedMessageId;
|
||||||
|
|
||||||
/// Create a new instance from a json
|
/// Create a new instance from JSON.
|
||||||
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(
|
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(
|
||||||
Serializer.moveToExtraDataFromRoot(json, topLevelFields),
|
Serializer.moveToExtraDataFromRoot(json, topLevelFields),
|
||||||
).copyWith(
|
).copyWith(
|
||||||
@@ -91,14 +91,14 @@ class Message extends Equatable {
|
|||||||
/// the message is added.
|
/// the message is added.
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
/// The text of this message
|
/// The text of this message.
|
||||||
final String? text;
|
final String? text;
|
||||||
|
|
||||||
/// The status of a sending message
|
/// The status of a sending message.
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
final MessageSendingStatus status;
|
final MessageSendingStatus status;
|
||||||
|
|
||||||
/// The message type
|
/// The message type.
|
||||||
@JsonKey(
|
@JsonKey(
|
||||||
includeIfNull: false,
|
includeIfNull: false,
|
||||||
toJson: Serializer.readOnly,
|
toJson: Serializer.readOnly,
|
||||||
@@ -110,15 +110,15 @@ class Message extends Equatable {
|
|||||||
@JsonKey(includeIfNull: false)
|
@JsonKey(includeIfNull: false)
|
||||||
final List<Attachment> attachments;
|
final List<Attachment> attachments;
|
||||||
|
|
||||||
/// The list of user mentioned in the message
|
/// The list of user mentioned in the message.
|
||||||
@JsonKey(toJson: User.toIds)
|
@JsonKey(toJson: User.toIds)
|
||||||
final List<User> mentionedUsers;
|
final List<User> mentionedUsers;
|
||||||
|
|
||||||
/// A map describing the count of number of every reaction
|
/// A map describing the count of number of every reaction.
|
||||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||||
final Map<String, int>? reactionCounts;
|
final Map<String, int>? reactionCounts;
|
||||||
|
|
||||||
/// A map describing the count of score of every reaction
|
/// A map describing the count of score of every reaction.
|
||||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||||
final Map<String, int>? reactionScores;
|
final Map<String, int>? reactionScores;
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ class Message extends Equatable {
|
|||||||
/// The ID of the parent message, if the message is a thread reply.
|
/// The ID of the parent message, if the message is a thread reply.
|
||||||
final String? parentId;
|
final String? parentId;
|
||||||
|
|
||||||
/// A quoted reply message
|
/// A quoted reply message.
|
||||||
@JsonKey(toJson: Serializer.readOnly)
|
@JsonKey(toJson: Serializer.readOnly)
|
||||||
final Message? quotedMessage;
|
final Message? quotedMessage;
|
||||||
|
|
||||||
@@ -153,10 +153,10 @@ class Message extends Equatable {
|
|||||||
/// Check if this message needs to show in the channel.
|
/// Check if this message needs to show in the channel.
|
||||||
final bool? showInChannel;
|
final bool? showInChannel;
|
||||||
|
|
||||||
/// If true the message is silent
|
/// If true the message is silent.
|
||||||
final bool silent;
|
final bool silent;
|
||||||
|
|
||||||
/// If true the message is shadowed
|
/// If true the message is shadowed.
|
||||||
@JsonKey(
|
@JsonKey(
|
||||||
includeIfNull: false,
|
includeIfNull: false,
|
||||||
toJson: Serializer.readOnly,
|
toJson: Serializer.readOnly,
|
||||||
@@ -169,6 +169,10 @@ class Message extends Equatable {
|
|||||||
|
|
||||||
final DateTime? _createdAt;
|
final DateTime? _createdAt;
|
||||||
|
|
||||||
|
/// Reserved field indicating when the message was deleted.
|
||||||
|
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||||
|
final DateTime? deletedAt;
|
||||||
|
|
||||||
/// Reserved field indicating when the message was created.
|
/// Reserved field indicating when the message was created.
|
||||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||||
DateTime get createdAt => _createdAt ?? DateTime.now();
|
DateTime get createdAt => _createdAt ?? DateTime.now();
|
||||||
@@ -179,48 +183,45 @@ class Message extends Equatable {
|
|||||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||||
DateTime get updatedAt => _updatedAt ?? DateTime.now();
|
DateTime get updatedAt => _updatedAt ?? DateTime.now();
|
||||||
|
|
||||||
/// User who sent the message
|
/// User who sent the message.
|
||||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||||
final User? user;
|
final User? user;
|
||||||
|
|
||||||
/// If true the message is pinned
|
/// If true the message is pinned.
|
||||||
final bool pinned;
|
final bool pinned;
|
||||||
|
|
||||||
/// Reserved field indicating when the message was pinned
|
/// Reserved field indicating when the message was pinned.
|
||||||
@JsonKey(toJson: Serializer.readOnly)
|
@JsonKey(toJson: Serializer.readOnly)
|
||||||
final DateTime? pinnedAt;
|
final DateTime? pinnedAt;
|
||||||
|
|
||||||
/// Reserved field indicating when the message will expire
|
/// Reserved field indicating when the message will expire.
|
||||||
///
|
///
|
||||||
/// if `null` message has no expiry
|
/// If `null` message has no expiry.
|
||||||
final DateTime? pinExpires;
|
final DateTime? pinExpires;
|
||||||
|
|
||||||
/// Reserved field indicating who pinned the message
|
/// Reserved field indicating who pinned the message.
|
||||||
@JsonKey(toJson: Serializer.readOnly)
|
@JsonKey(toJson: Serializer.readOnly)
|
||||||
final User? pinnedBy;
|
final User? pinnedBy;
|
||||||
|
|
||||||
/// Message custom extraData
|
/// Message custom extraData.
|
||||||
@JsonKey(includeIfNull: false)
|
@JsonKey(includeIfNull: false)
|
||||||
final Map<String, Object?> extraData;
|
final Map<String, Object?> extraData;
|
||||||
|
|
||||||
/// True if the message is a system info
|
/// True if the message is a system info.
|
||||||
bool get isSystem => type == 'system';
|
bool get isSystem => type == 'system';
|
||||||
|
|
||||||
/// True if the message has been deleted
|
/// True if the message has been deleted.
|
||||||
bool get isDeleted => type == 'deleted';
|
bool get isDeleted => type == 'deleted';
|
||||||
|
|
||||||
/// True if the message is ephemeral
|
/// True if the message is ephemeral.
|
||||||
bool get isEphemeral => type == 'ephemeral';
|
bool get isEphemeral => type == 'ephemeral';
|
||||||
|
|
||||||
/// Reserved field indicating when the message was deleted.
|
|
||||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
|
||||||
final DateTime? deletedAt;
|
|
||||||
|
|
||||||
/// A Map of translations.
|
/// A Map of translations.
|
||||||
@JsonKey(includeIfNull: false)
|
@JsonKey(includeIfNull: false)
|
||||||
final Map<String, String>? i18n;
|
final Map<String, String>? i18n;
|
||||||
|
|
||||||
/// Known top level fields.
|
/// Known top level fields.
|
||||||
|
///
|
||||||
/// Useful for [Serializer] methods.
|
/// Useful for [Serializer] methods.
|
||||||
static const topLevelFields = [
|
static const topLevelFields = [
|
||||||
'id',
|
'id',
|
||||||
@@ -253,7 +254,7 @@ class Message extends Equatable {
|
|||||||
'i18n',
|
'i18n',
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Serialize to json
|
/// Serialize to json.
|
||||||
Map<String, dynamic> toJson() => Serializer.moveFromExtraDataToRoot(
|
Map<String, dynamic> toJson() => Serializer.moveFromExtraDataToRoot(
|
||||||
_$MessageToJson(this),
|
_$MessageToJson(this),
|
||||||
);
|
);
|
||||||
@@ -265,6 +266,8 @@ class Message extends Equatable {
|
|||||||
String? type,
|
String? type,
|
||||||
List<Attachment>? attachments,
|
List<Attachment>? attachments,
|
||||||
List<User>? mentionedUsers,
|
List<User>? mentionedUsers,
|
||||||
|
bool? silent,
|
||||||
|
bool? shadowed,
|
||||||
Map<String, int>? reactionCounts,
|
Map<String, int>? reactionCounts,
|
||||||
Map<String, int>? reactionScores,
|
Map<String, int>? reactionScores,
|
||||||
List<Reaction>? latestReactions,
|
List<Reaction>? latestReactions,
|
||||||
@@ -275,8 +278,6 @@ class Message extends Equatable {
|
|||||||
int? replyCount,
|
int? replyCount,
|
||||||
List<User>? threadParticipants,
|
List<User>? threadParticipants,
|
||||||
bool? showInChannel,
|
bool? showInChannel,
|
||||||
bool? shadowed,
|
|
||||||
bool? silent,
|
|
||||||
String? command,
|
String? command,
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
DateTime? updatedAt,
|
DateTime? updatedAt,
|
||||||
@@ -304,6 +305,8 @@ class Message extends Equatable {
|
|||||||
type: type ?? this.type,
|
type: type ?? this.type,
|
||||||
attachments: attachments ?? this.attachments,
|
attachments: attachments ?? this.attachments,
|
||||||
mentionedUsers: mentionedUsers ?? this.mentionedUsers,
|
mentionedUsers: mentionedUsers ?? this.mentionedUsers,
|
||||||
|
silent: silent ?? this.silent,
|
||||||
|
shadowed: shadowed ?? this.shadowed,
|
||||||
reactionCounts: reactionCounts ?? this.reactionCounts,
|
reactionCounts: reactionCounts ?? this.reactionCounts,
|
||||||
reactionScores: reactionScores ?? this.reactionScores,
|
reactionScores: reactionScores ?? this.reactionScores,
|
||||||
latestReactions: latestReactions ?? this.latestReactions,
|
latestReactions: latestReactions ?? this.latestReactions,
|
||||||
@@ -316,18 +319,16 @@ class Message extends Equatable {
|
|||||||
showInChannel: showInChannel ?? this.showInChannel,
|
showInChannel: showInChannel ?? this.showInChannel,
|
||||||
command: command ?? this.command,
|
command: command ?? this.command,
|
||||||
createdAt: createdAt ?? _createdAt,
|
createdAt: createdAt ?? _createdAt,
|
||||||
silent: silent ?? this.silent,
|
|
||||||
extraData: extraData ?? this.extraData,
|
|
||||||
user: user ?? this.user,
|
|
||||||
shadowed: shadowed ?? this.shadowed,
|
|
||||||
updatedAt: updatedAt ?? _updatedAt,
|
updatedAt: updatedAt ?? _updatedAt,
|
||||||
deletedAt: deletedAt ?? this.deletedAt,
|
deletedAt: deletedAt ?? this.deletedAt,
|
||||||
status: status ?? this.status,
|
user: user ?? this.user,
|
||||||
pinned: pinned ?? this.pinned,
|
pinned: pinned ?? this.pinned,
|
||||||
pinnedAt: pinnedAt ?? this.pinnedAt,
|
pinnedAt: pinnedAt ?? this.pinnedAt,
|
||||||
pinnedBy: pinnedBy ?? this.pinnedBy,
|
|
||||||
pinExpires:
|
pinExpires:
|
||||||
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
||||||
|
pinnedBy: pinnedBy ?? this.pinnedBy,
|
||||||
|
extraData: extraData ?? this.extraData,
|
||||||
|
status: status ?? this.status,
|
||||||
i18n: i18n ?? this.i18n,
|
i18n: i18n ?? this.i18n,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -340,6 +341,8 @@ class Message extends Equatable {
|
|||||||
type: other.type,
|
type: other.type,
|
||||||
attachments: other.attachments,
|
attachments: other.attachments,
|
||||||
mentionedUsers: other.mentionedUsers,
|
mentionedUsers: other.mentionedUsers,
|
||||||
|
silent: other.silent,
|
||||||
|
shadowed: other.shadowed,
|
||||||
reactionCounts: other.reactionCounts,
|
reactionCounts: other.reactionCounts,
|
||||||
reactionScores: other.reactionScores,
|
reactionScores: other.reactionScores,
|
||||||
latestReactions: other.latestReactions,
|
latestReactions: other.latestReactions,
|
||||||
@@ -352,17 +355,15 @@ class Message extends Equatable {
|
|||||||
showInChannel: other.showInChannel,
|
showInChannel: other.showInChannel,
|
||||||
command: other.command,
|
command: other.command,
|
||||||
createdAt: other.createdAt,
|
createdAt: other.createdAt,
|
||||||
silent: other.silent,
|
|
||||||
extraData: other.extraData,
|
|
||||||
user: other.user,
|
|
||||||
shadowed: other.shadowed,
|
|
||||||
updatedAt: other.updatedAt,
|
updatedAt: other.updatedAt,
|
||||||
deletedAt: other.deletedAt,
|
deletedAt: other.deletedAt,
|
||||||
status: other.status,
|
user: other.user,
|
||||||
pinned: other.pinned,
|
pinned: other.pinned,
|
||||||
pinnedAt: other.pinnedAt,
|
pinnedAt: other.pinnedAt,
|
||||||
pinExpires: other.pinExpires,
|
pinExpires: other.pinExpires,
|
||||||
pinnedBy: other.pinnedBy,
|
pinnedBy: other.pinnedBy,
|
||||||
|
extraData: other.extraData,
|
||||||
|
status: other.status,
|
||||||
i18n: other.i18n,
|
i18n: other.i18n,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'dart:math';
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.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/emoji.dart';
|
||||||
import 'package:stream_chat_flutter/src/emoji_overlay.dart';
|
import 'package:stream_chat_flutter/src/emoji_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/extension.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/multi_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/quoted_message_widget.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/user_mentions_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/video_service.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/src/video_thumbnail_image.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.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';
|
import 'package:video_compress/video_compress.dart';
|
||||||
|
|
||||||
export 'package:video_compress/video_compress.dart' show VideoQuality;
|
export 'package:video_compress/video_compress.dart' show VideoQuality;
|
||||||
@@ -42,13 +37,14 @@ typedef ErrorListener = void Function(
|
|||||||
///
|
///
|
||||||
/// This callback should not throw.
|
/// 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(
|
typedef AttachmentLimitExceedListener = void Function(
|
||||||
int limit,
|
int limit,
|
||||||
String error,
|
String error,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Builder for attachment thumbnails
|
/// Builder for attachment thumbnails.
|
||||||
typedef AttachmentThumbnailBuilder = Widget Function(
|
typedef AttachmentThumbnailBuilder = Widget Function(
|
||||||
BuildContext,
|
BuildContext,
|
||||||
Attachment,
|
Attachment,
|
||||||
@@ -77,8 +73,8 @@ typedef ActionButtonBuilder = Widget Function(
|
|||||||
IconButton defaultActionButton,
|
IconButton defaultActionButton,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Widget builder for widgets that require may required data from the
|
/// Widget builder for widgets that may require data from the
|
||||||
/// [MessageInputController]
|
/// [MessageInputController].
|
||||||
typedef MessageRelatedBuilder = Widget Function(
|
typedef MessageRelatedBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
MessageInputController messageInputController,
|
MessageInputController messageInputController,
|
||||||
@@ -91,7 +87,7 @@ typedef AttachmentsPickerBuilder = Widget Function(
|
|||||||
StreamAttachmentPicker defaultPicker,
|
StreamAttachmentPicker defaultPicker,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Location for actions on the [MessageInput]
|
/// Location for actions on the [MessageInput].
|
||||||
enum ActionsLocation {
|
enum ActionsLocation {
|
||||||
/// Align to left
|
/// Align to left
|
||||||
left,
|
left,
|
||||||
@@ -106,7 +102,7 @@ enum ActionsLocation {
|
|||||||
rightInside,
|
rightInside,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default attachments for widget
|
/// Default attachments for widget.
|
||||||
enum DefaultAttachmentTypes {
|
enum DefaultAttachmentTypes {
|
||||||
/// Image Attachment
|
/// Image Attachment
|
||||||
image,
|
image,
|
||||||
@@ -118,7 +114,7 @@ enum DefaultAttachmentTypes {
|
|||||||
file,
|
file,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Available locations for the sendMessage button relative to the textField
|
/// Available locations for the `sendMessage` button relative to the textField.
|
||||||
enum SendButtonLocation {
|
enum SendButtonLocation {
|
||||||
/// inside the textField
|
/// inside the textField
|
||||||
inside,
|
inside,
|
||||||
@@ -131,17 +127,17 @@ const _kMinMediaPickerSize = 360.0;
|
|||||||
|
|
||||||
const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
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
|
/// ```dart
|
||||||
/// class ChannelPage extends StatelessWidget {
|
/// class ChannelPage extends StatelessWidget {
|
||||||
@@ -176,8 +172,7 @@ const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
|||||||
/// as the bottom widget.
|
/// as the bottom widget.
|
||||||
///
|
///
|
||||||
/// The widget renders the ui based on the first ancestor of
|
/// The widget renders the ui based on the first ancestor of
|
||||||
/// type [StreamChatTheme].
|
/// type [StreamChatTheme]. Modify it to change the widget appearance.
|
||||||
/// Modify it to change the widget appearance.
|
|
||||||
class MessageInput extends StatefulWidget {
|
class MessageInput extends StatefulWidget {
|
||||||
/// Instantiate a new MessageInput
|
/// Instantiate a new MessageInput
|
||||||
const MessageInput({
|
const MessageInput({
|
||||||
@@ -218,61 +213,60 @@ class MessageInput extends StatefulWidget {
|
|||||||
this.shouldKeepFocusAfterMessage,
|
this.shouldKeepFocusAfterMessage,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// List of options for showing overlays
|
/// List of options for showing overlays.
|
||||||
final List<OverlayOptions> customOverlays;
|
final List<OverlayOptions> customOverlays;
|
||||||
|
|
||||||
/// Video quality to use when compressing the videos
|
/// Video quality to use when compressing the videos.
|
||||||
final VideoQuality compressedVideoQuality;
|
final VideoQuality compressedVideoQuality;
|
||||||
|
|
||||||
/// Frame rate to use when compressing the videos
|
/// Frame rate to use when compressing the videos.
|
||||||
final int compressedVideoFrameRate;
|
final int compressedVideoFrameRate;
|
||||||
|
|
||||||
/// Max attachment size in bytes
|
/// Max attachment size in bytes:
|
||||||
/// Defaults to 20 MB
|
/// - Defaults to 20 MB
|
||||||
/// do not set it if you're using our default CDN
|
/// - Do not set it if you're using our default CDN
|
||||||
final int maxAttachmentSize;
|
final int maxAttachmentSize;
|
||||||
|
|
||||||
/// Function called after sending the message
|
/// Function called after sending the message.
|
||||||
final void Function(Message)? onMessageSent;
|
final void Function(Message)? onMessageSent;
|
||||||
|
|
||||||
/// Function called right before sending the message
|
/// Function called right before sending the message.
|
||||||
/// Use this to transform the message
|
///
|
||||||
|
/// Use this to transform the message.
|
||||||
final FutureOr<Message> Function(Message)? preMessageSending;
|
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;
|
final double maxHeight;
|
||||||
|
|
||||||
/// The keyboard type assigned to the TextField
|
/// The keyboard type assigned to the TextField.
|
||||||
final TextInputType keyboardType;
|
final TextInputType keyboardType;
|
||||||
|
|
||||||
/// If true the attachments button will not be displayed
|
/// If true the attachments button will not be displayed.
|
||||||
final bool disableAttachments;
|
final bool disableAttachments;
|
||||||
|
|
||||||
/// Use this property to hide/show the commands button
|
/// Use this property to hide/show the commands button.
|
||||||
final bool showCommandsButton;
|
final bool showCommandsButton;
|
||||||
|
|
||||||
/// Hide send as dm checkbox
|
/// Hide send as dm checkbox.
|
||||||
final bool hideSendAsDm;
|
final bool hideSendAsDm;
|
||||||
|
|
||||||
/// The text controller of the TextField
|
/// The text controller of the TextField.
|
||||||
final MessageInputController? messageInputController;
|
final MessageInputController? messageInputController;
|
||||||
|
|
||||||
/// List of action widgets
|
/// List of action widgets.
|
||||||
final List<Widget> actions;
|
final List<Widget> actions;
|
||||||
|
|
||||||
/// The location of the custom actions
|
/// The location of the custom actions.
|
||||||
final ActionsLocation actionsLocation;
|
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;
|
final Map<String, AttachmentThumbnailBuilder>? attachmentThumbnailBuilders;
|
||||||
|
|
||||||
/// The focus node associated to the TextField
|
/// The focus node associated to the TextField.
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
///
|
|
||||||
final Message? quotedMessage;
|
final Message? quotedMessage;
|
||||||
|
|
||||||
///
|
|
||||||
final VoidCallback? onQuotedMessageCleared;
|
final VoidCallback? onQuotedMessageCleared;
|
||||||
|
|
||||||
/// The location of the send button
|
/// The location of the send button
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ typedef CustomAttachmentIconBuilder = Widget Function(
|
|||||||
bool active,
|
bool active,
|
||||||
);
|
);
|
||||||
|
|
||||||
///
|
|
||||||
class StreamAttachmentPicker extends StatefulWidget {
|
class StreamAttachmentPicker extends StatefulWidget {
|
||||||
final bool isOpen;
|
final bool isOpen;
|
||||||
final double pickerSize;
|
final double pickerSize;
|
||||||
@@ -32,15 +31,15 @@ class StreamAttachmentPicker extends StatefulWidget {
|
|||||||
final ValueChanged<String>? onError;
|
final ValueChanged<String>? onError;
|
||||||
final FilePickerCallback onFilePicked;
|
final FilePickerCallback onFilePicked;
|
||||||
|
|
||||||
/// Video quality to use when compressing the videos
|
/// Video quality to use when compressing the videos.
|
||||||
final VideoQuality compressedVideoQuality;
|
final VideoQuality compressedVideoQuality;
|
||||||
|
|
||||||
/// Frame rate to use when compressing the videos
|
/// Frame rate to use when compressing the videos.
|
||||||
final int compressedVideoFrameRate;
|
final int compressedVideoFrameRate;
|
||||||
|
|
||||||
/// Max attachment size in bytes
|
/// Max attachment size in bytes:
|
||||||
/// Defaults to 20 MB
|
/// - Defaults to 20 MB
|
||||||
/// do not set it if you're using our default CDN
|
/// - Do not set it if you're using our default CDN
|
||||||
final int maxAttachmentSize;
|
final int maxAttachmentSize;
|
||||||
|
|
||||||
final List<DefaultAttachmentTypes> allowedAttachmentTypes;
|
final List<DefaultAttachmentTypes> allowedAttachmentTypes;
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export 'package:flutter/services.dart'
|
|||||||
class StreamMessageTextField extends StatefulWidget {
|
class StreamMessageTextField extends StatefulWidget {
|
||||||
/// Creates a Material Design text field.
|
/// Creates a Material Design text field.
|
||||||
///
|
///
|
||||||
/// If [decoration] is non-null (which is the default), the text field requires
|
/// If [decoration] is non-null (which is the default), the text field
|
||||||
/// one of its ancestors to be a [Material] widget.
|
/// requires one of its ancestors to be a [Material] widget.
|
||||||
///
|
///
|
||||||
/// To remove the decoration entirely (including the extra padding introduced
|
/// To remove the decoration entirely (including the extra padding introduced
|
||||||
/// by the decoration to save space for the labels), set the [decoration] to
|
/// 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.selectionHeightStyle = ui.BoxHeightStyle.tight,
|
||||||
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
|
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
|
||||||
this.keyboardAppearance,
|
this.keyboardAppearance,
|
||||||
this.scrollPadding = const EdgeInsets.all(20.0),
|
this.scrollPadding = const EdgeInsets.all(20),
|
||||||
this.dragStartBehavior = DragStartBehavior.start,
|
this.dragStartBehavior = DragStartBehavior.start,
|
||||||
this.enableInteractiveSelection = true,
|
this.enableInteractiveSelection = true,
|
||||||
this.selectionControls,
|
this.selectionControls,
|
||||||
@@ -127,34 +127,24 @@ class StreamMessageTextField extends StatefulWidget {
|
|||||||
this.autofillHints,
|
this.autofillHints,
|
||||||
this.restorationId,
|
this.restorationId,
|
||||||
this.enableIMEPersonalizedLearning = true,
|
this.enableIMEPersonalizedLearning = true,
|
||||||
}) : assert(textAlign != null),
|
}) : assert(obscuringCharacter.length == 1,
|
||||||
assert(readOnly != null),
|
'`obscuringCharacter.length` must be 1'),
|
||||||
assert(autofocus != null),
|
|
||||||
assert(obscuringCharacter != null && obscuringCharacter.length == 1),
|
|
||||||
assert(obscureText != null),
|
|
||||||
assert(autocorrect != null),
|
|
||||||
smartDashesType = smartDashesType ??
|
smartDashesType = smartDashesType ??
|
||||||
(obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
|
(obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
|
||||||
smartQuotesType = smartQuotesType ??
|
smartQuotesType = smartQuotesType ??
|
||||||
(obscureText ? SmartQuotesType.disabled : SmartQuotesType.enabled),
|
(obscureText ? SmartQuotesType.disabled : SmartQuotesType.enabled),
|
||||||
assert(enableSuggestions != null),
|
|
||||||
assert(enableInteractiveSelection != null),
|
|
||||||
assert(maxLengthEnforced != null),
|
|
||||||
assert(
|
assert(
|
||||||
maxLengthEnforced || maxLengthEnforcement == null,
|
maxLengthEnforced || maxLengthEnforcement == null,
|
||||||
'maxLengthEnforced is deprecated, use only maxLengthEnforcement',
|
'maxLengthEnforced is deprecated, use only maxLengthEnforcement',
|
||||||
),
|
),
|
||||||
assert(scrollPadding != null),
|
assert(maxLines == null || maxLines > 0,
|
||||||
assert(dragStartBehavior != null),
|
'`maxLines` needs to be left as null or bigger than 0'),
|
||||||
assert(selectionHeightStyle != null),
|
assert(minLines == null || minLines > 0,
|
||||||
assert(selectionWidthStyle != null),
|
'`minLines` needs to be left as null or bigger than 0'),
|
||||||
assert(maxLines == null || maxLines > 0),
|
|
||||||
assert(minLines == null || minLines > 0),
|
|
||||||
assert(
|
assert(
|
||||||
(maxLines == null) || (minLines == null) || (maxLines >= minLines),
|
(maxLines == null) || (minLines == null) || (maxLines >= minLines),
|
||||||
"minLines can't be greater than maxLines",
|
"minLines can't be greater than maxLines",
|
||||||
),
|
),
|
||||||
assert(expands != null),
|
|
||||||
assert(
|
assert(
|
||||||
!expands || (maxLines == null && minLines == null),
|
!expands || (maxLines == null && minLines == null),
|
||||||
'minLines and maxLines must be null when expands is true.',
|
'minLines and maxLines must be null when expands is true.',
|
||||||
@@ -164,14 +154,15 @@ class StreamMessageTextField extends StatefulWidget {
|
|||||||
assert(maxLength == null ||
|
assert(maxLength == null ||
|
||||||
maxLength == TextField.noMaxLength ||
|
maxLength == TextField.noMaxLength ||
|
||||||
maxLength > 0),
|
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(
|
assert(
|
||||||
!identical(textInputAction, TextInputAction.newline) ||
|
!identical(textInputAction, TextInputAction.newline) ||
|
||||||
maxLines == 1 ||
|
maxLines == 1 ||
|
||||||
!identical(keyboardType, TextInputType.text),
|
!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 ??
|
keyboardType = keyboardType ??
|
||||||
(maxLines == 1 ? TextInputType.text : TextInputType.multiline),
|
(maxLines == 1 ? TextInputType.text : TextInputType.multiline),
|
||||||
toolbarOptions = toolbarOptions ??
|
toolbarOptions = toolbarOptions ??
|
||||||
@@ -230,7 +221,8 @@ class StreamMessageTextField extends StatefulWidget {
|
|||||||
/// cause the focus to change, and will not make the keyboard visible.
|
/// cause the focus to change, and will not make the keyboard visible.
|
||||||
///
|
///
|
||||||
/// This widget builds an [EditableText] and will ensure that the keyboard is
|
/// 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;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
/// The decoration to show around the text field.
|
/// 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
|
/// If set, a character counter will be displayed below the
|
||||||
/// field showing how many characters have been entered. If set to a number
|
/// 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
|
/// 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
|
/// After [maxLength] characters have been input, additional input
|
||||||
/// is ignored, unless [maxLengthEnforcement] is set to
|
/// is ignored, unless [maxLengthEnforcement] is set to
|
||||||
/// [MaxLengthEnforcement.none].
|
/// [MaxLengthEnforcement.none].
|
||||||
///
|
///
|
||||||
/// The text field enforces the length with a [LengthLimitingTextInputFormatter],
|
/// The text field enforces the length with a
|
||||||
/// which is evaluated after the supplied [inputFormatters], if any.
|
/// [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
|
/// 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
|
/// 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.
|
/// 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.
|
/// 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;
|
final Brightness? keyboardAppearance;
|
||||||
|
|
||||||
/// {@macro flutter.widgets.editableText.scrollPadding}
|
/// {@macro flutter.widgets.editableText.scrollPadding}
|
||||||
@@ -490,14 +487,16 @@ class StreamMessageTextField extends StatefulWidget {
|
|||||||
/// widget.
|
/// widget.
|
||||||
///
|
///
|
||||||
/// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
|
/// 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.error].
|
||||||
/// * [MaterialState.hovered].
|
/// * [MaterialState.hovered].
|
||||||
/// * [MaterialState.focused].
|
/// * [MaterialState.focused].
|
||||||
/// * [MaterialState.disabled].
|
/// * [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
|
/// The [mouseCursor] is the only property of [TextField] that controls the
|
||||||
/// appearance of the mouse pointer. All other properties related to "cursor"
|
/// appearance of the mouse pointer. All other properties related to "cursor"
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
|
||||||
/// A value listenable builder related to a [Message]
|
/// A value listenable builder related to a [Message].
|
||||||
|
///
|
||||||
|
/// Pass in a [MessageInputController] as the `valueListenable`.
|
||||||
typedef MessageValueListenableBuilder = ValueListenableBuilder<Message>;
|
typedef MessageValueListenableBuilder = ValueListenableBuilder<Message>;
|
||||||
|
|
||||||
/// A function that returns true if the message is valid and can be sent.
|
/// A function that returns true if the message is valid and can be sent.
|
||||||
@@ -35,7 +37,7 @@ class MessageInputController extends ValueNotifier<Message> {
|
|||||||
validator: validator ?? _defaultValidator,
|
validator: validator ?? _defaultValidator,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Creates a controller for an editable text field from an initial
|
/// Creates a controller for an editable text field from initial
|
||||||
/// [attachments].
|
/// [attachments].
|
||||||
factory MessageInputController.fromAttachments(
|
factory MessageInputController.fromAttachments(
|
||||||
List<Attachment> attachments, {
|
List<Attachment> attachments, {
|
||||||
@@ -127,7 +129,7 @@ class MessageInputController extends ValueNotifier<Message> {
|
|||||||
/// Returns the start of the selection of the text field.
|
/// Returns the start of the selection of the text field.
|
||||||
int get selectionStart => textEditingController.selection.start;
|
int get selectionStart => textEditingController.selection.start;
|
||||||
|
|
||||||
/// Sets the showInChannel flag of the message.
|
/// Sets the [showInChannel] flag of the message.
|
||||||
set showInChannel(bool newValue) {
|
set showInChannel(bool newValue) {
|
||||||
value = value.copyWith(showInChannel: newValue);
|
value = value.copyWith(showInChannel: newValue);
|
||||||
}
|
}
|
||||||
@@ -202,14 +204,14 @@ class MessageInputController extends ValueNotifier<Message> {
|
|||||||
mentionedUsers = [];
|
mentionedUsers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the [value] to empty.
|
/// Sets the [message], or [value], to empty.
|
||||||
///
|
///
|
||||||
/// After calling this function, [text], [attachments] and [mentionedUsers]
|
/// After calling this function, [text], [attachments] and [mentionedUsers]
|
||||||
/// all will be empty.
|
/// will all be empty.
|
||||||
///
|
///
|
||||||
/// Calling this will notify all the listeners of this
|
/// Calling this will notify all the listeners of this
|
||||||
/// [MessageInputController] that they need to update
|
/// [MessageInputController] that they need to update
|
||||||
/// (it calls [notifyListeners]). For this reason,
|
/// (calls [notifyListeners]). For this reason,
|
||||||
/// this method should only be called between frames, e.g. in response to user
|
/// this method should only be called between frames, e.g. in response to user
|
||||||
/// actions, not during the build, layout, or paint phases.
|
/// actions, not during the build, layout, or paint phases.
|
||||||
void clear() {
|
void clear() {
|
||||||
@@ -217,7 +219,7 @@ class MessageInputController extends ValueNotifier<Message> {
|
|||||||
_textEditingController.clear();
|
_textEditingController.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the [value] to the initial [Message] value.
|
/// Sets the [value] to the initial [Message] value.
|
||||||
void reset({bool resetId = true}) {
|
void reset({bool resetId = true}) {
|
||||||
if (resetId) {
|
if (resetId) {
|
||||||
_initialMessage = _initialMessage.copyWith(
|
_initialMessage = _initialMessage.copyWith(
|
||||||
@@ -246,16 +248,13 @@ class RestorableMessageInputController
|
|||||||
extends RestorableChangeNotifier<MessageInputController> {
|
extends RestorableChangeNotifier<MessageInputController> {
|
||||||
/// Creates a [RestorableMessageInputController].
|
/// Creates a [RestorableMessageInputController].
|
||||||
///
|
///
|
||||||
/// This constructor treats a null `text` argument as if it were the empty
|
/// This constructor creates a default [Message] when no `message` argument
|
||||||
/// string.
|
/// is supplied.
|
||||||
RestorableMessageInputController({Message? message})
|
RestorableMessageInputController({Message? message})
|
||||||
: _initialValue = message ?? Message();
|
: _initialValue = message ?? Message();
|
||||||
|
|
||||||
/// Creates a [RestorableMessageInputController] from an initial
|
/// Creates a [RestorableMessageInputController] from an initial
|
||||||
/// [TextEditingValue].
|
/// [text] value.
|
||||||
///
|
|
||||||
/// This constructor treats a null `value` argument as if it were
|
|
||||||
/// [TextEditingValue.empty].
|
|
||||||
factory RestorableMessageInputController.fromText(String? text) =>
|
factory RestorableMessageInputController.fromText(String? text) =>
|
||||||
RestorableMessageInputController(message: Message(text: text));
|
RestorableMessageInputController(message: Message(text: text));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user