chore(repo): remove deprecated code.
Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
@@ -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}
|
||||
/// 
|
||||
/// 
|
||||
///
|
||||
/// 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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
-2
@@ -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';
|
||||
|
||||
-2
@@ -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';
|
||||
|
||||
-2
@@ -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)],
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user