chore(repo): remove deprecated code.

Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
Sahil Kumar
2023-07-18 16:35:35 +05:30
parent 406ed66d1b
commit 972a0f5993
44 changed files with 38 additions and 1300 deletions
@@ -17,7 +17,6 @@ import 'package:stream_chat/src/core/http/stream_http_client.dart';
import 'package:stream_chat/src/core/http/token.dart';
import 'package:stream_chat/src/core/http/token_manager.dart';
import 'package:stream_chat/src/core/models/attachment_file.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/channel_state.dart';
import 'package:stream_chat/src/core/models/event.dart';
import 'package:stream_chat/src/core/models/filter.dart';
@@ -572,8 +571,6 @@ class StreamChatClient {
/// Requests channels with a given query.
Stream<List<Channel>> queryChannels({
Filter? filter,
@Deprecated('Use channelStateSort instead.')
List<SortOption<ChannelModel>>? sort,
List<SortOption<ChannelState>>? channelStateSort,
bool state = true,
bool watch = true,
@@ -590,7 +587,7 @@ class StreamChatClient {
final hash = generateHash([
filter,
sort,
channelStateSort,
state,
watch,
presence,
@@ -604,8 +601,6 @@ class StreamChatClient {
} else {
final channels = await queryChannelsOffline(
filter: filter,
// ignore: deprecated_member_use_from_same_package
sort: sort,
channelStateSort: channelStateSort,
paginationParams: paginationParams,
);
@@ -614,7 +609,7 @@ class StreamChatClient {
try {
final newQueryChannelsFuture = queryChannelsOnline(
filter: filter,
sort: channelStateSort ?? sort,
sort: channelStateSort,
state: state,
watch: watch,
presence: presence,
@@ -731,17 +726,11 @@ class StreamChatClient {
/// Requests channels with a given query from the Persistence client.
Future<List<Channel>> queryChannelsOffline({
Filter? filter,
@Deprecated('''
sort has been deprecated.
Please use channelStateSort instead.''')
List<SortOption<ChannelModel>>? sort,
List<SortOption<ChannelState>>? channelStateSort,
PaginationParams paginationParams = const PaginationParams(),
}) async {
final offlineChannels = (await chatPersistenceClient?.getChannelStates(
filter: filter,
// ignore: deprecated_member_use_from_same_package
sort: sort,
channelStateSort: channelStateSort,
paginationParams: paginationParams,
)) ??
@@ -13,7 +13,6 @@ class RetryPolicy {
/// Instantiate a new RetryPolicy
RetryPolicy({
required this.shouldRetry,
@Deprecated("Use 'delayFactor' instead.") this.retryTimeout,
this.maxRetryAttempts = 6,
this.delayFactor = const Duration(milliseconds: 200),
this.randomizationFactor = 0.25,
@@ -53,13 +52,4 @@ class RetryPolicy {
int attempt,
StreamChatError? error,
) shouldRetry;
/// In the case that we want to retry a failed request the retryTimeout
/// method is called to determine the timeout
@Deprecated("Use 'delayFactor' instead.")
final Duration Function(
StreamChatClient client,
int attempt,
StreamChatError? error,
)? retryTimeout;
}
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
@@ -88,11 +88,6 @@ class StreamChatNetworkError extends StreamChatError {
this.isRequestCancelledError = false,
}) : super(message);
///
@Deprecated('Use `StreamChatNetworkError.fromDioException` instead')
factory StreamChatNetworkError.fromDioError(DioException error) =
StreamChatNetworkError.fromDioException;
///
factory StreamChatNetworkError.fromDioException(DioException exception) {
final response = exception.response;
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/user.dart';
@@ -15,70 +15,6 @@ class _NullConst {
const _nullConst = _NullConst();
/// Enum defining the status of a sending message.
enum MessageSendingStatus {
/// Message is being sent
sending,
/// Message is being updated
updating,
/// Message is being deleted
deleting,
/// Message failed to send
failed,
/// Message failed to updated
// ignore: constant_identifier_names
failed_update,
/// Message failed to delete
// ignore: constant_identifier_names
failed_delete,
/// Message correctly sent
sent;
/// Returns a [MessageState] from a [MessageSendingStatus]
MessageState toMessageState() {
switch (this) {
case MessageSendingStatus.sending:
return MessageState.sending;
case MessageSendingStatus.updating:
return MessageState.updating;
case MessageSendingStatus.deleting:
return MessageState.softDeleting;
case MessageSendingStatus.failed:
return MessageState.sendingFailed;
case MessageSendingStatus.failed_update:
return MessageState.updatingFailed;
case MessageSendingStatus.failed_delete:
return MessageState.softDeletingFailed;
case MessageSendingStatus.sent:
return MessageState.sent;
}
}
/// Returns a [MessageSendingStatus] from a [MessageState].
static MessageSendingStatus fromMessageState(MessageState state) {
return state.when(
initial: () => MessageSendingStatus.sending,
outgoing: (it) => it.when(
sending: () => MessageSendingStatus.sending,
updating: () => MessageSendingStatus.updating,
deleting: (_) => MessageSendingStatus.deleting,
),
completed: (_) => MessageSendingStatus.sent,
failed: (it, __) => it.when(
sendingFailed: () => MessageSendingStatus.failed,
updatingFailed: () => MessageSendingStatus.failed_update,
deletingFailed: (_) => MessageSendingStatus.failed_delete,
),
);
}
}
/// The class that contains the information about a message.
@JsonSerializable()
class Message extends Equatable {
@@ -114,23 +50,14 @@ class Message extends Equatable {
DateTime? pinExpires,
this.pinnedBy,
this.extraData = const {},
@Deprecated('Use `state` instead') MessageSendingStatus? status,
MessageState? state,
this.state = const MessageState.initial(),
this.i18n,
}) : id = id ?? const Uuid().v4(),
pinExpires = pinExpires?.toUtc(),
remoteCreatedAt = createdAt,
remoteUpdatedAt = updatedAt,
remoteDeletedAt = deletedAt,
_quotedMessageId = quotedMessageId {
var messageState = state ?? const MessageState.initial();
// Backward compatibility. TODO: Remove in the next major version
if (status != null) {
messageState = status.toMessageState();
}
this.state = messageState;
}
_quotedMessageId = quotedMessageId;
/// Create a new instance from JSON.
factory Message.fromJson(Map<String, dynamic> json) {
@@ -155,17 +82,9 @@ class Message extends Equatable {
/// The text of this message.
final String? text;
/// The status of a sending message.
@Deprecated('Use `state` instead')
@JsonKey(includeFromJson: false, includeToJson: false)
MessageSendingStatus get status {
return MessageSendingStatus.fromMessageState(state);
}
// TODO: Remove late modifier in the next major version.
/// The current state of the message.
@JsonKey(includeFromJson: false, includeToJson: false)
late final MessageState state;
final MessageState state;
/// The message type.
@JsonKey(includeToJson: false)
@@ -381,7 +300,6 @@ class Message extends Equatable {
Object? pinExpires = _nullConst,
User? pinnedBy,
Map<String, Object?>? extraData,
@Deprecated('Use `state` instead') MessageSendingStatus? status,
MessageState? state,
Map<String, String>? i18n,
}) {
@@ -416,8 +334,6 @@ class Message extends Equatable {
return true;
}(), 'Validate type for quotedMessage');
final messageState = state ?? status?.toMessageState();
return Message(
id: id ?? this.id,
text: text ?? this.text,
@@ -454,7 +370,7 @@ class Message extends Equatable {
pinExpires == _nullConst ? this.pinExpires : pinExpires as DateTime?,
pinnedBy: pinnedBy ?? this.pinnedBy,
extraData: extraData ?? this.extraData,
state: messageState ?? this.state,
state: state ?? this.state,
i18n: i18n ?? this.i18n,
);
}
@@ -102,8 +102,6 @@ abstract class ChatPersistenceClient {
/// for filtering out states.
Future<List<ChannelState>> getChannelStates({
Filter? filter,
@Deprecated('Use channelStateSort instead.')
List<SortOption<ChannelModel>>? sort,
List<SortOption<ChannelState>>? channelStateSort,
PaginationParams? paginationParams,
});
@@ -62,8 +62,6 @@ class TestPersistenceClient extends ChatPersistenceClient {
@override
Future<List<ChannelState>> getChannelStates(
{Filter? filter,
@Deprecated('Use channelStateSort instead.')
List<SortOption<ChannelModel>>? sort,
List<SortOption<ChannelState>>? channelStateSort,
PaginationParams? paginationParams}) =>
throw UnimplementedError();
@@ -1,510 +0,0 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:collection/collection.dart'
show IterableExtension, ListEquality;
import 'package:contextmenu/contextmenu.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/context_menu_items/stream_chat_context_menu_item.dart';
import 'package:stream_chat_flutter/src/dialogs/dialogs.dart';
import 'package:stream_chat_flutter/src/message_widget/sending_indicator_builder.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@template channelPreview}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/channel_preview.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/channel_preview_paint.png)
///
/// Shows a preview for the current [Channel].
///
/// Uses a [StreamBuilder] to render the channel information image as soon as
/// it updates.
///
/// It is not recommended to use this widget directly as it is the
/// default channel preview widget used by [ChannelListView].
///
/// The UI is rendered based on the first ancestor of type [StreamChatTheme].
/// Modify it to change the widget's appearance.
/// {@endtemplate}
@Deprecated('Use StreamChannelListTile instead.')
class ChannelPreview extends StatelessWidget {
/// {@macro channelPreview}
const ChannelPreview({
required this.channel,
super.key,
this.onTap,
this.onLongPress,
this.onViewInfoTap,
this.onImageTap,
this.title,
this.subtitle,
this.leading,
this.sendingIndicator,
this.trailing,
});
/// The action to perform when this widget is tapped or clicked.
final void Function(Channel)? onTap;
/// The action to perform when this widget is long pressed.
final void Function(Channel)? onLongPress;
/// The action to perform when 'View Info' is tapped or clicked.
final ViewInfoCallback? onViewInfoTap;
/// The [Channel] being previewed.
final Channel channel;
/// The action to perform when the image is tapped
final VoidCallback? onImageTap;
/// Widget rendering the title
final Widget? title;
/// Widget rendering the subtitle
final Widget? subtitle;
/// Widget rendering the leading element. By default it shows the
/// [StreamChannelAvatar].
final Widget? leading;
/// Widget rendering the trailing element. By default it shows the date of
/// the last message.
final Widget? trailing;
/// Widget rendering the sending indicator. By default it uses the
/// [StreamSendingIndicator] widget.
final Widget? sendingIndicator;
@override
Widget build(BuildContext context) {
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
final streamChatState = StreamChat.of(context);
final streamChatTheme = StreamChatTheme.of(context);
return BetterStreamBuilder<bool>(
stream: channel.isMutedStream,
initialData: channel.isMuted,
builder: (context, data) => AnimatedOpacity(
opacity: data ? 0.5 : 1,
duration: const Duration(milliseconds: 300),
child: ContextMenuArea(
verticalPadding: 0,
builder: (context) => [
StreamChatContextMenuItem(
leading: StreamSvgIcon.user(
color: Colors.grey,
),
title: Text(context.translations.viewInfoLabel),
onClick: () {
Navigator.of(context, rootNavigator: true).pop();
if (onViewInfoTap != null) {
onViewInfoTap?.call(channel);
} else {
showDialog(
context: context,
builder: (_) => ChannelInfoDialog(
channel: channel,
),
);
}
},
),
StreamChatContextMenuItem(
leading: StreamSvgIcon.mute(
color: Colors.grey,
),
title: channel.isGroup
? Text(
context.translations
.toggleMuteUnmuteGroupText(isMuted: channel.isMuted),
)
: Text(
context.translations
.toggleMuteUnmuteUserText(isMuted: channel.isMuted),
),
onClick: () async {
Navigator.of(context, rootNavigator: true).pop();
showDialog(
context: context,
builder: (_) => ConfirmationDialog(
titleText: channel.isGroup
? context.translations
.toggleMuteUnmuteGroupText(isMuted: channel.isMuted)
: context.translations
.toggleMuteUnmuteUserText(isMuted: channel.isMuted),
promptText: channel.isGroup
? context.translations.toggleMuteUnmuteGroupQuestion(
isMuted: channel.isMuted,
)
: context.translations.toggleMuteUnmuteUserQuestion(
isMuted: channel.isMuted,
),
affirmativeText: context.translations
.toggleMuteUnmuteAction(isMuted: channel.isMuted),
onConfirmation: () async {
try {
if (channel.isMuted) {
await channel.unmute();
} else {
await channel.mute();
}
} catch (e) {
showDialog(
context: context,
builder: (_) => MessageDialog(
messageText: e.toString(),
),
);
}
},
),
);
},
),
if (channel.isGroup)
StreamChatContextMenuItem(
leading: StreamSvgIcon.userRemove(
color: Colors.red,
),
title: Text(
context.translations.leaveGroupLabel,
style: const TextStyle(
color: Colors.red,
),
),
onClick: () {
Navigator.of(context, rootNavigator: true).pop();
showDialog(
context: context,
builder: (_) => ConfirmationDialog(
titleText: context.translations.leaveGroupLabel,
promptText:
context.translations.leaveConversationQuestion,
affirmativeText: context.translations.leaveLabel,
onConfirmation: () async {
final userAsMember = channel.state?.members.firstWhere(
(e) =>
e.user?.id ==
StreamChat.of(context).currentUser?.id,
);
try {
await channel.removeMembers([userAsMember!.user!.id]);
} catch (e) {
showDialog(
context: context,
builder: (_) => MessageDialog(
messageText: e.toString(),
),
);
}
},
),
);
},
),
if (!channel.isGroup)
StreamChatContextMenuItem(
leading: StreamSvgIcon.delete(
color: Colors.red,
),
title: Text(
context.translations.deleteConversationLabel,
style: const TextStyle(
color: Colors.red,
),
),
onClick: () {
Navigator.of(context, rootNavigator: true).pop();
showDialog(
context: context,
builder: (_) => ConfirmationDialog(
titleText: context.translations.deleteConversationLabel,
promptText:
context.translations.deleteConversationQuestion,
affirmativeText: context.translations.deleteLabel,
onConfirmation: () async {
try {
await channel.delete();
} catch (e) {
showDialog(
context: context,
builder: (_) => MessageDialog(
messageText: e.toString(),
),
);
}
},
),
);
},
),
],
child: ListTile(
visualDensity: VisualDensity.compact,
contentPadding: const EdgeInsets.symmetric(
horizontal: 8,
),
onTap: () => onTap?.call(channel),
onLongPress: () => onLongPress?.call(channel),
leading: leading ??
StreamChannelAvatar(
onTap: onImageTap,
channel: channel,
),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: title ??
ChannelName(
textStyle: channelPreviewTheme.titleStyle,
),
),
BetterStreamBuilder<List<Member>>(
stream: channel.state?.membersStream,
initialData: channel.state?.members,
comparator: const ListEquality().equals,
builder: (context, members) {
if (members.isEmpty ||
!members.any((Member e) =>
e.user!.id ==
channel.client.state.currentUser?.id)) {
return const SizedBox();
}
return StreamUnreadIndicator(
cid: channel.cid,
);
},
),
],
),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(child: subtitle ?? _Subtitle(channel: channel)),
sendingIndicator ??
Builder(
builder: (context) {
final lastMessage =
channel.state?.messages.lastWhereOrNull(
(m) => !m.isDeleted && !m.shadowed,
);
if (lastMessage?.user?.id ==
streamChatState.currentUser?.id) {
return Padding(
padding: const EdgeInsets.only(right: 4),
child: BetterStreamBuilder<List<Read>>(
stream: channel.state?.readStream,
initialData: channel.state?.read,
builder: (context, data) {
final hasNonUrlAttachments = lastMessage!
.attachments
.where((it) =>
it.titleLink == null ||
it.type == 'giphy')
.isNotEmpty;
return SendingIndicatorBuilder(
messageTheme: streamChatTheme.ownMessageTheme,
message: lastMessage,
hasNonUrlAttachments: hasNonUrlAttachments,
streamChat: streamChatState,
streamChatTheme: streamChatTheme,
channel: channel,
);
},
),
);
}
return const SizedBox();
},
),
trailing ?? _Date(channel: channel),
],
),
),
),
),
);
}
}
class _Date extends StatelessWidget {
const _Date({
required this.channel,
});
final Channel channel;
@override
Widget build(BuildContext context) {
return BetterStreamBuilder<DateTime>(
stream: channel.lastMessageAtStream,
initialData: channel.lastMessageAt,
builder: (context, data) {
final lastMessageAt = data.toLocal();
String stringDate;
final now = DateTime.now();
final startOfDay = DateTime(now.year, now.month, now.day);
if (lastMessageAt.millisecondsSinceEpoch >=
startOfDay.millisecondsSinceEpoch) {
stringDate = Jiffy.parseFromDateTime(lastMessageAt.toLocal()).jm;
} else if (lastMessageAt.millisecondsSinceEpoch >=
startOfDay
.subtract(const Duration(days: 1))
.millisecondsSinceEpoch) {
stringDate = context.translations.yesterdayLabel;
} else if (startOfDay.difference(lastMessageAt).inDays < 7) {
stringDate = Jiffy.parseFromDateTime(lastMessageAt.toLocal()).EEEE;
} else {
stringDate = Jiffy.parseFromDateTime(lastMessageAt.toLocal()).yMd;
}
return Text(
stringDate,
style: StreamChannelPreviewTheme.of(context).lastMessageAtStyle,
);
},
);
}
}
class _Subtitle extends StatelessWidget {
const _Subtitle({
required this.channel,
});
final Channel channel;
@override
Widget build(BuildContext context) {
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
if (channel.isMuted) {
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
StreamSvgIcon.mute(
size: 16,
),
Text(
' ${context.translations.channelIsMutedText}',
style: channelPreviewTheme.subtitleStyle,
),
],
);
}
return StreamTypingIndicator(
channel: channel,
alternativeWidget: _LastMessage(
channel: channel,
),
style: channelPreviewTheme.subtitleStyle,
);
}
}
class _LastMessage extends StatelessWidget {
const _LastMessage({
required this.channel,
});
final Channel channel;
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.centerLeft,
child: BetterStreamBuilder<List<Message>>(
stream: channel.state!.messagesStream,
initialData: channel.state!.messages,
builder: (context, data) {
final lastMessage =
data.lastWhereOrNull((m) => !m.shadowed && !m.isDeleted);
if (lastMessage == null) {
return const SizedBox();
}
var text = lastMessage.text;
final parts = <String>[
...lastMessage.attachments.map((e) {
if (e.type == 'image') {
return '📷';
} else if (e.type == 'video') {
return '🎬';
} else if (e.type == 'giphy') {
return '[GIF]';
}
return e == lastMessage.attachments.last
? (e.title ?? 'File')
: '${e.title ?? 'File'} , ';
}),
lastMessage.text ?? '',
];
text = parts.join(' ');
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
return Text.rich(
_getDisplayText(
text,
lastMessage.mentionedUsers,
lastMessage.attachments,
channelPreviewTheme.subtitleStyle?.copyWith(
color: channelPreviewTheme.subtitleStyle?.color,
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
? FontStyle.italic
: FontStyle.normal,
),
channelPreviewTheme.subtitleStyle?.copyWith(
color: channelPreviewTheme.subtitleStyle?.color,
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
? FontStyle.italic
: FontStyle.normal,
fontWeight: FontWeight.bold,
),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.start,
);
},
),
);
}
TextSpan _getDisplayText(
String text,
List<User> mentions,
List<Attachment> attachments,
TextStyle? normalTextStyle,
TextStyle? mentionsTextStyle,
) {
final textList = text.split(' ');
final resList = <TextSpan>[];
for (final e in textList) {
if (mentions.isNotEmpty &&
mentions.any((element) => '@${element.name}' == e)) {
resList.add(TextSpan(
text: '$e ',
style: mentionsTextStyle,
));
} else if (attachments.isNotEmpty &&
attachments
.where((e) => e.title != null)
.any((element) => element.title == e)) {
resList.add(TextSpan(
text: '$e ',
style: normalTextStyle?.copyWith(fontStyle: FontStyle.italic),
));
} else {
resList.add(TextSpan(
text: e == textList.last ? e : '$e ',
style: normalTextStyle,
));
}
}
return TextSpan(children: resList);
}
}
@@ -1,12 +0,0 @@
// TODO: remove in v6 as this is no longer used. Currently exported.
/// Return action for coming back from pages
@Deprecated('''
ReturnActionType has been deprecated and is no longer used.''')
enum ReturnActionType {
/// No return action
none,
/// Go to reply message action
reply,
}
@@ -81,10 +81,7 @@ abstract class Translations {
/// The text for showing the unread messages count
/// in the [StreamMessageListView]
String unreadMessagesSeparatorText(
@Deprecated('unreadCount is not used anymore and will be removed ')
int unreadCount,
);
String unreadMessagesSeparatorText();
/// The label for "connected" in [StreamConnectionStatusBuilder]
String get connectedLabel;
@@ -802,7 +799,7 @@ Attachment limit exceeded: it's not possible to add more than $limit attachments
String get linkDisabledError => 'Links are disabled';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'New messages';
String unreadMessagesSeparatorText() => 'New messages';
@override
String get enableFileAccessMessage => 'Please enable access to files'
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'dart:async';
import 'dart:math';
@@ -110,8 +108,6 @@ class StreamMessageInput extends StatefulWidget {
this.mediaAttachmentListBuilder,
this.fileAttachmentBuilder,
this.mediaAttachmentBuilder,
@Deprecated('Use `mediaAttachmentBuilder` instead.')
this.attachmentThumbnailBuilders,
this.focusNode,
this.sendButtonLocation = SendButtonLocation.outside,
this.autofocus = false,
@@ -235,10 +231,6 @@ class StreamMessageInput extends StatefulWidget {
/// Builder used to build the media attachment item.
final AttachmentItemBuilder? mediaAttachmentBuilder;
/// Map that defines a thumbnail builder for an attachment type.
@Deprecated('Use `mediaAttachmentBuilder` instead.')
final Map<String, AttachmentThumbnailBuilder>? attachmentThumbnailBuilders;
/// Map that defines a thumbnail builder for an attachment type.
///
/// This is used to build the thumbnail for the attachment in the quoted
@@ -1220,44 +1212,7 @@ class StreamMessageInputState extends State<StreamMessageInput>
fileAttachmentListBuilder: widget.fileAttachmentListBuilder,
mediaAttachmentListBuilder: widget.mediaAttachmentListBuilder,
fileAttachmentBuilder: widget.fileAttachmentBuilder,
mediaAttachmentBuilder: widget.mediaAttachmentBuilder ??
// For backward compatibility.
// TODO: Remove in the next major release.
(context, attachment, onRemovePressed) {
final Widget mediaAttachmentThumbnail;
final builder =
widget.attachmentThumbnailBuilders?[attachment.type];
if (builder != null) {
mediaAttachmentThumbnail = builder(context, attachment);
} else {
mediaAttachmentThumbnail = MessageInputMediaAttachmentThumbnail(
attachment: attachment,
);
}
return ClipRRect(
key: Key(attachment.id),
borderRadius: BorderRadius.circular(10),
child: Stack(
children: <Widget>[
AspectRatio(
aspectRatio: 1,
child: mediaAttachmentThumbnail,
),
Positioned(
top: 8,
right: 8,
child: RemoveAttachmentButton(
onPressed: onRemovePressed != null
? () => onRemovePressed(attachment)
: null,
),
),
],
),
);
},
mediaAttachmentBuilder: widget.mediaAttachmentBuilder,
),
);
}
@@ -1,7 +1,5 @@
// ignore_for_file: lines_longer_than_80_chars
import 'dart:async';
import 'dart:math' as math;
import 'dart:ui';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
@@ -97,11 +95,6 @@ class StreamMessageListView extends StatefulWidget {
this.initialAlignment,
this.scrollController,
this.itemPositionListener,
@Deprecated(
'Try wrapping the `MessageWidget` with a `Swipeable`, `Dismissible` or a '
'custom widget to achieve the swipe to reply behaviour.',
)
this.onMessageSwiped,
this.highlightInitialMessage = false,
this.messageHighlightColor,
this.showConnectionStateTile = false,
@@ -215,9 +208,6 @@ class StreamMessageListView extends StatefulWidget {
/// The ScrollPhysics used by the ListView
final ScrollPhysics? scrollPhysics;
/// {@macro onMessageSwiped}
final OnMessageSwiped? onMessageSwiped;
/// If true the list will highlight the initialMessage if there is any.
///
/// Also See [StreamChannel]
@@ -1263,76 +1253,6 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
);
}
// Add swipeable if the callback is provided and the message is not deleted,
// system or ephemeral.
final onMessageSwiped = widget.onMessageSwiped;
if (onMessageSwiped != null &&
!message.isDeleted &&
!message.isSystem &&
!message.isEphemeral) {
// The threshold after which the message is considered swiped.
const threshold = 0.2;
// The direction in which the message can be swiped.
final swipeDirection = isMyMessage
? SwipeDirection.endToStart //
: SwipeDirection.startToEnd;
child = Swipeable(
key: ValueKey(message.id),
direction: swipeDirection,
swipeThreshold: threshold,
onSwiped: (_) => onMessageSwiped(message),
backgroundBuilder: (context, details) {
// The alignment of the swipe action.
final alignment = isMyMessage
? Alignment.centerRight //
: Alignment.centerLeft;
// The progress of the swipe action.
final progress = math.min(details.progress, threshold) / threshold;
// The offset for the reply icon.
var offset = Offset.lerp(
const Offset(-24, 0),
const Offset(12, 0),
progress,
)!;
// If the message is mine, we need to flip the offset.
if (isMyMessage) {
offset = Offset(-offset.dx, -offset.dy);
}
return Align(
alignment: alignment,
child: Transform.translate(
offset: offset,
child: Opacity(
opacity: progress,
child: SizedBox.square(
dimension: 30,
child: CustomPaint(
painter: AnimatedCircleBorderPainter(
progress: progress,
color: _streamTheme.colorTheme.borders,
),
child: Center(
child: StreamSvgIcon.reply(
size: lerpDouble(0, 18, progress),
color: _streamTheme.colorTheme.accentPrimary,
),
),
),
),
),
),
);
},
child: child,
);
}
return child;
}
@@ -24,7 +24,7 @@ class UnreadMessagesSeparator extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
context.translations.unreadMessagesSeparatorText(unreadCount),
context.translations.unreadMessagesSeparatorText(),
textAlign: TextAlign.center,
style: StreamChannelHeaderTheme.of(context).subtitleStyle,
),
@@ -55,9 +55,7 @@ class StreamMessageWidget extends StatefulWidget {
this.attachmentBorderRadiusGeometry,
this.onMentionTap,
this.onMessageTap,
bool? showReactionPicker,
@Deprecated('Use `showReactionPicker` instead')
bool showReactionPickerIndicator = true,
this.showReactionPicker = true,
@internal this.showReactionPickerTail = false,
this.showUserAvatar = DisplayWidget.show,
this.showSendingIndicator = true,
@@ -86,15 +84,7 @@ class StreamMessageWidget extends StatefulWidget {
this.quotedMessageBuilder,
this.editMessageInputBuilder,
this.textBuilder,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.bottomRowBuilder,
this.bottomRowBuilderWithDefaultWidget,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.deletedBottomRowBuilder,
this.customAttachmentBuilders,
this.padding,
this.textPadding = const EdgeInsets.symmetric(
@@ -106,20 +96,11 @@ class StreamMessageWidget extends StatefulWidget {
this.onQuotedMessageTap,
this.customActions = const [],
this.onAttachmentTap,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.usernameBuilder,
this.imageAttachmentThumbnailSize = const Size(400, 400),
this.imageAttachmentThumbnailResizeType = 'clip',
this.imageAttachmentThumbnailCropType = 'center',
this.attachmentActionsModalBuilder,
}) : assert(
bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null,
'You can only use one of the two bottom row builders',
),
showReactionPicker = showReactionPicker ?? showReactionPickerIndicator,
attachmentBuilders = {
}) : attachmentBuilders = {
'image': (context, message, attachments) {
final border = RoundedRectangleBorder(
side: attachmentBorderSide ??
@@ -329,32 +310,17 @@ class StreamMessageWidget extends StatefulWidget {
/// {@endtemplate}
final Widget Function(BuildContext, Message)? textBuilder;
/// {@template usernameBuilder}
/// Widget builder for building username
/// {@endtemplate}
final Widget Function(BuildContext, Message)? usernameBuilder;
/// {@template onMessageActions}
/// Function called on long press
/// {@endtemplate}
final void Function(BuildContext, Message)? onMessageActions;
/// {@template bottomRowBuilder}
/// Widget builder for building a bottom row below the message
/// {@endtemplate}
final BottomRowBuilder? bottomRowBuilder;
/// {@template bottomRowBuilderWithDefaultWidget}
/// Widget builder for building a bottom row below the message.
/// Also contains the default bottom row widget.
/// {@endtemplate}
final BottomRowBuilderWithDefaultWidget? bottomRowBuilderWithDefaultWidget;
/// {@template deletedBottomRowBuilder}
/// Widget builder for building a bottom row below a deleted message
/// {@endtemplate}
final Widget Function(BuildContext, Message)? deletedBottomRowBuilder;
/// {@template userAvatarBuilder}
/// Widget builder for building user avatar
/// {@endtemplate}
@@ -471,11 +437,6 @@ class StreamMessageWidget extends StatefulWidget {
/// {@endtemplate}
final bool showReactionPicker;
/// {@template showReactionPickerIndicator}
/// Used in [StreamMessageReactionsModal] and [MessageActionsModal]
/// {@endtemplate} @Deprecated('Use `showReactionPicker` instead')
bool get showReactionPickerIndicator => showReactionPicker;
/// {@template showReactionPickerTail}
/// Whether or not to show the reaction picker tail
/// {@endtemplate}
@@ -601,19 +562,7 @@ class StreamMessageWidget extends StatefulWidget {
Widget Function(BuildContext, Message)? editMessageInputBuilder,
Widget Function(BuildContext, Message)? textBuilder,
Widget Function(BuildContext, Message)? quotedMessageBuilder,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') Widget Function(BuildContext, Message)? usernameBuilder,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') BottomRowBuilder? bottomRowBuilder,
BottomRowBuilderWithDefaultWidget? bottomRowBuilderWithDefaultWidget,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') Widget Function(BuildContext, Message)? deletedBottomRowBuilder,
void Function(BuildContext, Message)? onMessageActions,
Message? message,
StreamMessageThemeData? messageTheme,
@@ -637,8 +586,6 @@ class StreamMessageWidget extends StatefulWidget {
void Function(User)? onUserAvatarTap,
void Function(String)? onLinkTap,
bool? showReactionPicker,
@Deprecated('Use `showReactionPicker` instead')
bool? showReactionPickerIndicator,
@internal bool? showReactionPickerTail,
List<Read>? readList,
ShowMessageCallback? onShowMessage,
@@ -665,29 +612,6 @@ class StreamMessageWidget extends StatefulWidget {
String? imageAttachmentThumbnailCropType,
AttachmentActionsBuilder? attachmentActionsModalBuilder,
}) {
assert(
bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null,
'You can only use one of the two bottom row builders',
);
var _bottomRowBuilderWithDefaultWidget =
bottomRowBuilderWithDefaultWidget ??
this.bottomRowBuilderWithDefaultWidget;
_bottomRowBuilderWithDefaultWidget ??= (context, message, defaultWidget) {
final _bottomRowBuilder = bottomRowBuilder ?? this.bottomRowBuilder;
if (_bottomRowBuilder != null) {
return _bottomRowBuilder(context, message);
}
return defaultWidget.copyWith(
onThreadTap: onThreadTap ?? this.onThreadTap,
usernameBuilder: usernameBuilder ?? this.usernameBuilder,
deletedBottomRowBuilder:
deletedBottomRowBuilder ?? this.deletedBottomRowBuilder,
);
};
return StreamMessageWidget(
key: key ?? this.key,
onMentionTap: onMentionTap ?? this.onMentionTap,
@@ -698,7 +622,8 @@ class StreamMessageWidget extends StatefulWidget {
editMessageInputBuilder ?? this.editMessageInputBuilder,
textBuilder: textBuilder ?? this.textBuilder,
quotedMessageBuilder: quotedMessageBuilder ?? this.quotedMessageBuilder,
bottomRowBuilderWithDefaultWidget: _bottomRowBuilderWithDefaultWidget,
bottomRowBuilderWithDefaultWidget: bottomRowBuilderWithDefaultWidget ??
this.bottomRowBuilderWithDefaultWidget,
onMessageActions: onMessageActions ?? this.onMessageActions,
message: message ?? this.message,
messageTheme: messageTheme ?? this.messageTheme,
@@ -723,9 +648,7 @@ class StreamMessageWidget extends StatefulWidget {
showInChannelIndicator ?? this.showInChannelIndicator,
onUserAvatarTap: onUserAvatarTap ?? this.onUserAvatarTap,
onLinkTap: onLinkTap ?? this.onLinkTap,
showReactionPicker: showReactionPicker ??
showReactionPickerIndicator ??
this.showReactionPicker,
showReactionPicker: showReactionPicker ?? this.showReactionPicker,
showReactionPickerTail:
showReactionPickerTail ?? this.showReactionPickerTail,
onShowMessage: onShowMessage ?? this.onShowMessage,
@@ -941,23 +864,6 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
: Alignment.centerLeft,
widthFactor: widget.widthFactor,
child: Builder(builder: (context) {
var _bottomRowBuilderWithDefaultWidget =
widget.bottomRowBuilderWithDefaultWidget;
_bottomRowBuilderWithDefaultWidget ??=
(context, message, defaultWidget) {
final _bottomRowBuilder = widget.bottomRowBuilder;
if (_bottomRowBuilder != null) {
return _bottomRowBuilder(context, message);
}
return defaultWidget.copyWith(
onThreadTap: widget.onThreadTap,
usernameBuilder: widget.usernameBuilder,
deletedBottomRowBuilder: widget.deletedBottomRowBuilder,
);
};
return MessageWidgetContent(
streamChatTheme: _streamChatTheme,
showUsername: showUsername,
@@ -999,7 +905,7 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
onMentionTap: widget.onMentionTap,
onQuotedMessageTap: widget.onQuotedMessageTap,
bottomRowBuilderWithDefaultWidget:
_bottomRowBuilderWithDefaultWidget,
widget.bottomRowBuilderWithDefaultWidget,
onUserAvatarTap: widget.onUserAvatarTap,
userAvatarBuilder: widget.userAvatarBuilder,
);
@@ -1249,7 +1155,7 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
showSendingIndicator: false,
padding: EdgeInsets.zero,
// Show both the tail and indicator if the indicator is shown.
showReactionPickerTail: widget.showReactionPickerIndicator,
showReactionPickerTail: widget.showReactionPicker,
showPinHighlight: false,
showUserAvatar: widget.message.user!.id ==
channel.client.state.currentUser!.id
@@ -1271,7 +1177,7 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
showResendMessage: shouldShowResendAction,
showCopyMessage: shouldShowCopyAction,
showEditMessage: shouldShowEditAction,
showReactionPicker: widget.showReactionPickerIndicator,
showReactionPicker: widget.showReactionPicker,
showReplyMessage: shouldShowReplyAction,
showThreadReplyMessage: shouldShowThreadReplyAction,
showFlagButton: widget.showFlagButton,
@@ -67,28 +67,9 @@ class MessageWidgetContent extends StatelessWidget {
this.onLinkTap,
this.textBuilder,
this.quotedMessageBuilder,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.bottomRowBuilder,
this.bottomRowBuilderWithDefaultWidget,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.onThreadTap,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.deletedBottomRowBuilder,
this.userAvatarBuilder,
@Deprecated('''
Use [bottomRowBuilderWithDefaultWidget] instead.
Will be removed in the next major version.
''') this.usernameBuilder,
}) : assert(
bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null,
'You can only use one of the two bottom row builders',
);
});
/// {@macro reverse}
final bool reverse;
@@ -191,9 +172,6 @@ class MessageWidgetContent extends StatelessWidget {
/// The padding to use for this widget.
final double bottomRowPadding;
/// {@macro bottomRowBuilder}
final BottomRowBuilder? bottomRowBuilder;
/// {@macro bottomRowBuilderWithDefaultWidget}
final BottomRowBuilderWithDefaultWidget? bottomRowBuilderWithDefaultWidget;
@@ -215,21 +193,12 @@ class MessageWidgetContent extends StatelessWidget {
/// {@macro showUsername}
final bool showUsername;
/// {@macro onThreadTap}
final void Function(Message)? onThreadTap;
/// {@macro deletedBottomRowBuilder}
final Widget Function(BuildContext, Message)? deletedBottomRowBuilder;
/// {@macro messageWidget}
final StreamMessageWidget messageWidget;
/// {@macro userAvatarBuilder}
final Widget Function(BuildContext, User)? userAvatarBuilder;
/// {@macro usernameBuilder}
final Widget Function(BuildContext, Message)? usernameBuilder;
@override
Widget build(BuildContext context) {
return Column(
@@ -457,16 +426,11 @@ class MessageWidgetContent extends StatelessWidget {
showTimeStamp: showTimeStamp,
showUsername: showUsername,
streamChatTheme: streamChatTheme,
onThreadTap: onThreadTap,
deletedBottomRowBuilder: deletedBottomRowBuilder,
streamChat: streamChat,
hasNonUrlAttachments: hasNonUrlAttachments,
usernameBuilder: usernameBuilder,
);
if (bottomRowBuilder != null) {
return bottomRowBuilder!(context, message);
} else if (bottomRowBuilderWithDefaultWidget != null) {
if (bottomRowBuilderWithDefaultWidget != null) {
return bottomRowBuilderWithDefaultWidget!(
context,
message,
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_error_widget.dart';
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_error_widget.dart';
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/scroll_view/stream_scroll_view_error_widget.dart';
@@ -22,16 +22,13 @@ class StreamMessageThemeData with Diagnosticable {
this.reactionsMaskColor,
this.avatarTheme,
this.createdAtStyle,
@Deprecated('Use urlAttachmentBackgroundColor instead')
Color? linkBackgroundColor,
Color? urlAttachmentBackgroundColor,
this.urlAttachmentBackgroundColor,
this.urlAttachmentHostStyle,
this.urlAttachmentTitleStyle,
this.urlAttachmentTextStyle,
this.urlAttachmentTitleMaxLine,
this.urlAttachmentTextMaxLine,
}) : urlAttachmentBackgroundColor =
urlAttachmentBackgroundColor ?? linkBackgroundColor;
});
/// Text style for message text
final TextStyle? messageTextStyle;
@@ -66,10 +63,6 @@ class StreamMessageThemeData with Diagnosticable {
/// Theme of the avatar
final StreamAvatarThemeData? avatarTheme;
/// Background color for messages with url attachments.
@Deprecated('Use urlAttachmentBackgroundColor instead')
Color? get linkBackgroundColor => urlAttachmentBackgroundColor;
/// Background color for messages with url attachments.
final Color? urlAttachmentBackgroundColor;
@@ -101,8 +94,6 @@ class StreamMessageThemeData with Diagnosticable {
Color? reactionsBackgroundColor,
Color? reactionsBorderColor,
Color? reactionsMaskColor,
@Deprecated('Use urlAttachmentBackgroundColor instead')
Color? linkBackgroundColor,
Color? urlAttachmentBackgroundColor,
TextStyle? urlAttachmentHostStyle,
TextStyle? urlAttachmentTitleStyle,
@@ -124,9 +115,8 @@ class StreamMessageThemeData with Diagnosticable {
reactionsBackgroundColor ?? this.reactionsBackgroundColor,
reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor,
reactionsMaskColor: reactionsMaskColor ?? this.reactionsMaskColor,
urlAttachmentBackgroundColor: urlAttachmentBackgroundColor ??
linkBackgroundColor ??
this.urlAttachmentBackgroundColor,
urlAttachmentBackgroundColor:
urlAttachmentBackgroundColor ?? this.urlAttachmentBackgroundColor,
urlAttachmentHostStyle:
urlAttachmentHostStyle ?? this.urlAttachmentHostStyle,
urlAttachmentTitleStyle:
@@ -1,88 +0,0 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@template streamUserItem}
/// Shows a preview of the current [User].
///
/// This widget uses a [StreamBuilder] to render the user information
/// image as soon as it updates.
///
/// It is not recommended to use this widget as it's the default user preview
/// used by [StreamUserListView].
///
/// The widget renders the ui based on the first ancestor of type
/// [StreamChatTheme].
/// Modify it to change the widget's appearance.
/// {@endtemplate}
@Deprecated('Use `StreamUserListTile` instead.')
class StreamUserItem extends StatelessWidget {
/// {@macro streamUserItem}
const StreamUserItem({
super.key,
required this.user,
this.onTap,
this.onLongPress,
this.onImageTap,
this.selected = false,
this.showLastOnline = true,
});
/// Function called when tapping or clicking on this widget
final void Function(User)? onTap;
/// Function called when long pressing this widget
final void Function(User)? onLongPress;
/// The user to display
final User user;
/// The function called when the image is tapped or clicked
final void Function(User)? onImageTap;
/// If true the [StreamUserItem] will show a trailing checkmark
final bool selected;
/// If true the [StreamUserItem] will show the last seen
final bool showLastOnline;
@override
Widget build(BuildContext context) {
final chatThemeData = StreamChatTheme.of(context);
return ListTile(
onTap: onTap == null ? null : () => onTap!(user),
onLongPress: onLongPress == null ? null : () => onLongPress!(user),
leading: StreamUserAvatar(
user: user,
onTap: onImageTap,
constraints: const BoxConstraints.tightFor(
height: 40,
width: 40,
),
),
trailing: selected
? StreamSvgIcon.checkSend(
color: chatThemeData.colorTheme.accentPrimary,
)
: null,
title: Text(
user.name,
style: chatThemeData.textTheme.bodyBold,
),
subtitle: showLastOnline ? _buildLastActive(context) : null,
);
}
Widget _buildLastActive(BuildContext context) {
final chatTheme = StreamChatTheme.of(context);
final lastActive = user.lastActive ?? DateTime.now();
return Text(
user.online
? context.translations.userOnlineText
: '${context.translations.userLastOnlineText} '
'${Jiffy.parseFromDateTime(lastActive).fromNow()}',
style: chatTheme.textTheme.footnote.copyWith(
color: chatTheme.colorTheme.textHighEmphasis.withOpacity(0.5),
),
);
}
}
@@ -59,29 +59,6 @@ bool getEffectiveCenterTitle(
}
}
/// Shows confirmation dialog
@Deprecated(
'''
showConfirmationDialog is deprecated.
Use showConfirmationBottomSheet instead.''',
)
Future<bool?> showConfirmationDialog(
BuildContext context, {
required String title,
required String okText,
Widget? icon,
String? question,
String? cancelText,
}) =>
showConfirmationBottomSheet(
context,
title: title,
okText: okText,
icon: icon,
question: question,
cancelText: cancelText,
);
/// Shows confirmation bottom sheet
Future<bool?> showConfirmationBottomSheet(
BuildContext context, {
@@ -169,29 +146,6 @@ Future<bool?> showConfirmationBottomSheet(
);
}
/// Shows info dialog
@Deprecated(
'''
showInfoDialog is deprecated.
Use showInfoBottomSheet instead.''',
)
Future<bool?> showInfoDialog(
BuildContext context, {
required String title,
required String okText,
Widget? icon,
String? details,
StreamChatThemeData? theme,
}) =>
showInfoBottomSheet(
context,
title: title,
okText: okText,
icon: icon,
details: details,
theme: theme,
);
/// Shows info bottom sheet
Future<bool?> showInfoBottomSheet(
BuildContext context, {
@@ -418,25 +372,6 @@ StreamSvgIcon getFileTypeImage(String? mimeType) {
}
}
/// Wraps attachment widget with custom shape
@Deprecated(
'''
wrapAttachmentWidget is deprecated.
Use WrapAttachmentWidget instead
''',
)
Widget wrapAttachmentWidget(
BuildContext context,
Widget attachmentWidget,
ShapeBorder attachmentShape,
// ignore: avoid_positional_boolean_parameters
bool reverse,
) =>
WrapAttachmentWidget(
attachmentWidget: attachmentWidget,
attachmentShape: attachmentShape,
);
/// Wraps attachment widget with custom shape
class WrapAttachmentWidget extends StatelessWidget {
/// Builds a [WrapAttachmentWidget].
@@ -60,14 +60,12 @@ typedef OnUserAvatarPress = void Function(User);
typedef PlaceholderUserImage = Widget Function(BuildContext, User);
/// {@template editMessageInputBuilder}
// ignore: deprecated_member_use_from_same_package
/// A widget builder for building a pre-populated [MessageInput] for use in
/// editing messages.
/// {@endtemplate}
typedef EditMessageInputBuilder = Widget Function(BuildContext, Message);
/// {@template channelListHeaderTitleBuilder}
// ignore: deprecated_member_use_from_same_package
/// A widget builder for custom [ChannelListHeader] title widgets.
/// {@endtemplate}
typedef ChannelListHeaderTitleBuilder = Widget Function(
@@ -87,12 +85,6 @@ typedef ChannelTapCallback = void Function(Channel, Widget?);
/// {@endtemplate}
typedef ChannelInfoCallback = void Function(Channel);
/// {@template channelPreviewBuilder}
/// Builder used to create a custom ChannelPreview for a [Channel]
/// {@endtemplate}
@Deprecated('Use StreamChannelListViewIndexedWidgetBuilder instead')
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
/// {@template viewInfoCallback}
/// Callback for when 'View Info' is tapped
/// {@endtemplate}
@@ -164,7 +156,6 @@ typedef MentionTileOverlayBuilder = Widget Function(
/// {@template userMentionTileBuilder}
/// A builder function for representing a custom user mention tile.
///
// ignore: deprecated_member_use_from_same_package
/// Use [UserMentionTile] for the default implementation.
/// {@endtemplate}
typedef UserMentionTileBuilder = Widget Function(
@@ -232,7 +223,6 @@ typedef OnMessageTap = void Function(Message);
/// {@template messageSearchItemTapCallback}
/// The action to perform when tapping or clicking on a user in a
// ignore: deprecated_member_use_from_same_package
/// [MessageSearchListView].
/// {@endtemplate}
typedef MessageSearchItemTapCallback = void Function(GetMessageResponse);
@@ -26,11 +26,9 @@ export 'src/channel/channel_header.dart';
export 'src/channel/channel_info.dart';
export 'src/channel/channel_list_header.dart';
export 'src/channel/channel_name.dart';
export 'src/channel/channel_preview.dart';
export 'src/channel/stream_channel_avatar.dart';
export 'src/channel/stream_channel_name.dart';
export 'src/channel/stream_message_preview_text.dart';
export 'src/fullscreen_media/fsm_enums.dart';
export 'src/fullscreen_media/full_screen_media.dart';
export 'src/fullscreen_media/full_screen_media_builder.dart';
export 'src/gallery/gallery_footer.dart';
@@ -93,7 +91,6 @@ export 'src/stream_chat.dart';
export 'src/stream_chat_configuration.dart';
export 'src/theme/stream_chat_theme.dart';
export 'src/theme/themes.dart';
export 'src/user/user_item.dart';
export 'src/user/user_mention_tile.dart';
export 'src/utils/device_segmentation.dart';
export 'src/utils/extensions.dart';
@@ -1,97 +0,0 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import '../mocks.dart';
void main() {
testWidgets(
'it should show basic channel information',
(WidgetTester tester) async {
final client = MockClient();
final clientState = MockClientState();
final channel = MockChannel();
final channelState = MockChannelState();
final user = OwnUser(id: 'user-id');
final lastMessageAt = DateTime.parse('2020-06-22 12:00:00');
when(() => channel.cid).thenReturn('cid');
when(() => client.state).thenReturn(clientState);
when(() => clientState.currentUser).thenReturn(user);
when(() => clientState.currentUserStream)
.thenAnswer((_) => Stream.value(user));
when(() => channel.lastMessageAtStream)
.thenAnswer((_) => Stream.value(lastMessageAt));
when(() => channel.lastMessageAt).thenReturn(lastMessageAt);
when(() => channel.state).thenReturn(channelState);
when(() => channel.client).thenReturn(client);
when(() => channel.isMuted).thenReturn(false);
when(() => channel.isMutedStream).thenAnswer((i) => Stream.value(false));
when(() => channel.nameStream)
.thenAnswer((i) => Stream.value('test name'));
when(() => channel.name).thenReturn('test name');
when(() => channel.imageStream)
.thenAnswer((i) => Stream.value('https://bit.ly/321RmWb'));
when(() => channel.image).thenReturn('https://bit.ly/321RmWb');
when(() => clientState.channels).thenReturn({
channel.cid!: channel,
});
when(() => channelState.unreadCount).thenReturn(1);
when(() => channelState.unreadCountStream)
.thenAnswer((i) => Stream.value(1));
when(() => channelState.membersStream).thenAnswer(
(i) => Stream.value([
Member(
userId: 'user-id',
user: User(id: 'user-id'),
)
]),
);
when(() => channelState.members).thenReturn([
Member(
userId: 'user-id',
user: User(id: 'user-id'),
),
]);
when(() => channelState.messages).thenReturn([
Message(
text: 'hello',
user: User(id: 'other-user'),
)
]);
when(() => channelState.messagesStream).thenAnswer(
(i) => Stream.value([
Message(
text: 'hello',
user: User(id: 'other-user'),
)
]),
);
await tester.pumpWidget(
MaterialApp(
home: StreamChat(
client: client,
child: StreamChannel(
channel: channel,
child: Scaffold(
body: ChannelPreview(
channel: channel,
),
),
),
),
),
);
expect(find.text('6/22/2020'), findsOneWidget);
expect(find.text('test name'), findsOneWidget);
expect(find.text('1'), findsOneWidget);
expect(find.text('hello'), findsOneWidget);
expect(find.byType(StreamChannelAvatar), findsOneWidget);
},
);
}
@@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
@@ -44,9 +44,6 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
required this.client,
StreamChannelListEventHandler? eventHandler,
this.filter,
@Deprecated('''
sort has been deprecated.
Please use channelStateSort instead.''') this.sort,
this.channelStateSort,
this.presence = true,
this.limit = defaultChannelPagedLimit,
@@ -62,9 +59,6 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
StreamChannelListEventHandler? eventHandler,
this.filter,
this.channelStateSort,
@Deprecated('''
sort has been deprecated.
Please use channelStateSort instead.''') this.sort,
this.presence = true,
this.limit = defaultChannelPagedLimit,
this.messageLimit,
@@ -84,20 +78,6 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
/// You can also filter other built-in channel fields.
final Filter? filter;
/// The sorting used for the channels matching the filters.
///
/// Sorting is based on field and direction, multiple sorting options
/// can be provided.
///
/// You can sort based on last_updated, last_message_at, updated_at,
/// created_at or member_count.
///
/// Direction can be ascending or descending.
@Deprecated('''
sort has been deprecated.
Please use channelStateSort instead.''')
final List<SortOption<ChannelModel>>? sort;
/// The sorting used for the channels matching the filters.
///
/// Sorting is based on field and direction, multiple sorting options
@@ -132,8 +112,6 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
await for (final channels in client.queryChannels(
filter: filter,
channelStateSort: channelStateSort,
// ignore: deprecated_member_use, deprecated_member_use_from_same_package
sort: sort,
memberLimit: memberLimit,
messageLimit: messageLimit,
presence: presence,
@@ -162,8 +140,6 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
try {
await for (final channels in client.queryChannels(
filter: filter,
// ignore: deprecated_member_use, deprecated_member_use_from_same_package
sort: sort,
channelStateSort: channelStateSort,
memberLimit: memberLimit,
messageLimit: messageLimit,
@@ -461,7 +461,7 @@ class NnStreamChatLocalizations extends GlobalStreamChatLocalizations {
String get viewLibrary => 'View library';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'New messages';
String unreadMessagesSeparatorText() => 'New messages';
@override
String get enableFileAccessMessage => 'Enable file access to continue';
@@ -440,7 +440,7 @@ class StreamChatLocalizationsCa extends GlobalStreamChatLocalizations {
String get linkDisabledError => 'Els enllaços estan deshabilitats';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Missatges nous';
String unreadMessagesSeparatorText() => 'Missatges nous';
@override
String get enableFileAccessMessage => "Habilita l'accés als fitxers"
@@ -433,7 +433,7 @@ class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations {
String get viewLibrary => 'Bibliothek öffnen';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Neue Nachrichten';
String unreadMessagesSeparatorText() => 'Neue Nachrichten';
@override
String get enableFileAccessMessage =>
@@ -437,7 +437,7 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations {
String get viewLibrary => 'View library';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'New messages';
String unreadMessagesSeparatorText() => 'New messages';
@override
String get enableFileAccessMessage => 'Please enable access to files'
@@ -442,7 +442,7 @@ No es posible añadir más de $limit archivos adjuntos
String get linkDisabledError => 'Los enlaces están deshabilitados';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Nuevos mensajes';
String unreadMessagesSeparatorText() => 'Nuevos mensajes';
@override
String get enableFileAccessMessage => 'Habilite el acceso a los archivos'
@@ -441,7 +441,7 @@ Limite de pièces jointes dépassée : il n'est pas possible d'ajouter plus de $
String get linkDisabledError => 'Les liens sont désactivés';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Nouveaux messages';
String unreadMessagesSeparatorText() => 'Nouveaux messages';
@override
String get enableFileAccessMessage =>
@@ -435,7 +435,7 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
String get linkDisabledError => 'लिंक भेजना प्रतिबंधित';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'नए संदेश।';
String unreadMessagesSeparatorText() => 'नए संदेश।';
@override
String get enableFileAccessMessage => 'कृपया फ़ाइलों तक पहुंच सक्षम करें ताकि'
@@ -444,7 +444,7 @@ Attenzione: il limite massimo di $limit file è stato superato.
String get linkDisabledError => 'I links sono disattivati';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Nouveaux messages';
String unreadMessagesSeparatorText() => 'Nouveaux messages';
@override
String get enableFileAccessMessage => "Per favore attiva l'accesso ai file"
@@ -420,7 +420,7 @@ class StreamChatLocalizationsJa extends GlobalStreamChatLocalizations {
String get linkDisabledError => 'リンクが無効になっています';
@override
String unreadMessagesSeparatorText(int unreadCount) => '新しいメッセージ。';
String unreadMessagesSeparatorText() => '新しいメッセージ。';
@override
String get enableFileAccessMessage =>
@@ -421,7 +421,7 @@ class StreamChatLocalizationsKo extends GlobalStreamChatLocalizations {
String get linkDisabledError => '링크가 비활성화되었습니다.';
@override
String unreadMessagesSeparatorText(int unreadCount) => '새 메시지.';
String unreadMessagesSeparatorText() => '새 메시지.';
@override
String get enableFileAccessMessage => '친구와 공유할 수 있도록 파일에 대한 액세스를 허용하세요.';
@@ -385,7 +385,7 @@ class StreamChatLocalizationsNo extends GlobalStreamChatLocalizations {
String get viewLibrary => 'Se bibliotek';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Nye meldinger.';
String unreadMessagesSeparatorText() => 'Nye meldinger.';
@override
String get couldNotReadBytesFromFileError =>
@@ -440,7 +440,7 @@ Não é possível adicionar mais de $limit arquivos de uma vez
String get viewLibrary => 'Ver biblioteca';
@override
String unreadMessagesSeparatorText(int unreadCount) => 'Novas mensagens';
String unreadMessagesSeparatorText() => 'Novas mensagens';
@override
String get enableFileAccessMessage =>
@@ -196,7 +196,7 @@ void main() {
localizations.toggleMuteUnmuteUserQuestion(isMuted: true), isNotNull);
expect(localizations.toggleMuteUnmuteUserText(isMuted: true), isNotNull);
expect(localizations.viewLibrary, isNotNull);
expect(localizations.unreadMessagesSeparatorText(2), isNotNull);
expect(localizations.unreadMessagesSeparatorText(), isNotNull);
expect(localizations.enableFileAccessMessage, isNotNull);
expect(localizations.allowFileAccessMessage, isNotNull);
});
@@ -251,39 +251,18 @@ class StreamChatPersistenceClient extends ChatPersistenceClient {
@override
Future<List<ChannelState>> getChannelStates({
Filter? filter,
@Deprecated('Use channelStateSort instead.')
List<SortOption<ChannelModel>>? sort,
List<SortOption<ChannelState>>? channelStateSort,
PaginationParams? paginationParams,
}) async {
assert(_debugIsConnected, '');
assert(
sort == null || channelStateSort == null,
'sort and channelStateSort cannot be used together',
);
_logger.info('getChannelStates');
final channels = await db!.channelQueryDao.getChannels(
filter: filter,
sort: sort,
);
final channels = await db!.channelQueryDao.getChannels(filter: filter);
final channelStates = await Future.wait(
channels.map((e) => getChannelStateByCid(e.cid)),
);
// Only sort the channel states if the channels are not already sorted.
if (sort == null) {
var comparator = _defaultChannelStateComparator;
if (channelStateSort != null && channelStateSort.isNotEmpty) {
comparator = _combineComparators(
channelStateSort.map((it) => it.comparator).withNullifyer,
);
}
channelStates.sort(comparator);
}
final offset = paginationParams?.offset;
if (offset != null && offset > 0 && channelStates.isNotEmpty) {
channelStates.removeRange(0, offset);
@@ -421,35 +400,3 @@ class StreamChatPersistenceClient extends ChatPersistenceClient {
}
}
}
// Creates a new combined [Comparator] which sorts items
// by the given [comparators].
Comparator<T> _combineComparators<T>(Iterable<Comparator<T>> comparators) {
return (T a, T b) {
for (final comparator in comparators) {
try {
final result = comparator(a, b);
if (result != 0) return result;
} catch (e) {
// If the comparator throws an exception, we ignore it and
// continue with the next comparator.
continue;
}
}
return 0;
};
}
// The default [Comparator] used to sort [ChannelState]s.
int _defaultChannelStateComparator(ChannelState a, ChannelState b) {
final dateA = a.channel?.lastMessageAt ?? a.channel?.createdAt;
final dateB = b.channel?.lastMessageAt ?? b.channel?.createdAt;
if (dateA == null && dateB == null) return 0;
if (dateA == null) return 1;
if (dateB == null) {
return -1;
} else {
return dateB.compareTo(dateA);
}
}
@@ -148,7 +148,6 @@ void main() {
// Should match with the inserted channels
final updatedChannels = await channelQueryDao.getChannels(
filter: filter,
// ignore: deprecated_member_use_from_same_package
sort: [
SortOption(
'member_count',
@@ -196,7 +195,6 @@ void main() {
// Should match with the inserted channels
final updatedChannels = await channelQueryDao.getChannels(
filter: filter,
// ignore: deprecated_member_use_from_same_package
sort: [SortOption('test_custom_field', comparator: sortComparator)],
);