diff --git a/packages/stream_chat/lib/src/api/channel.dart b/packages/stream_chat/lib/src/api/channel.dart index 09992d98..e9291568 100644 --- a/packages/stream_chat/lib/src/api/channel.dart +++ b/packages/stream_chat/lib/src/api/channel.dart @@ -1685,8 +1685,7 @@ class ChannelClientState { ...messages!, ]; - newThreads[parentId]! - .sort(_sortByCreatedAt as int Function(Message, Message)?); + newThreads[parentId]!.sort(_sortByCreatedAt); } else { newThreads[parentId] = messages; } @@ -1713,7 +1712,7 @@ class ChannelClientState { .any((newMessage) => newMessage.id == m.id) != true) .toList(), - ]..sort(_sortByCreatedAt as int Function(Message, Message)?); + ]..sort(_sortByCreatedAt); final newWatchers = [ ...updatedState.watchers, @@ -1752,17 +1751,8 @@ class ChannelClientState { ); } - int? _sortByCreatedAt(a, b) { - if (a.createdAt == null) { - return 1; - } - - if (b.createdAt == null) { - return -1; - } - - return a.createdAt.compareTo(b.createdAt); - } + int _sortByCreatedAt(Message a, Message b) => + a.createdAt.compareTo(b.createdAt); /// The channel state related to this client ChannelState get _channelState => _channelStateController.value!; diff --git a/packages/stream_chat/lib/src/db/chat_persistence_client.dart b/packages/stream_chat/lib/src/db/chat_persistence_client.dart index 9f4c7afe..479743b2 100644 --- a/packages/stream_chat/lib/src/db/chat_persistence_client.dart +++ b/packages/stream_chat/lib/src/db/chat_persistence_client.dart @@ -7,6 +7,7 @@ import 'package:stream_chat/src/models/message.dart'; import 'package:stream_chat/src/models/reaction.dart'; import 'package:stream_chat/src/models/read.dart'; import 'package:stream_chat/src/models/user.dart'; +import 'package:stream_chat/src/extensions/iterable_extension.dart'; /// A simple client used for persisting chat data locally. abstract class ChatPersistenceClient { @@ -78,7 +79,7 @@ abstract class ChatPersistenceClient { return ChannelState( members: data[0] as List, read: data[1] as List, - channel: data[2] as ChannelModel, + channel: data[2] as ChannelModel?, messages: data[3] as List, pinnedMessages: data[4] as List, ); @@ -192,17 +193,17 @@ abstract class ChatPersistenceClient { deleteMembers, ]); - final channels = cleanedChannelStates - .map((it) => it.channel) - .where((it) => it != null) as Iterable; + final channels = cleanedChannelStates.map((it) => it.channel).withNullifyer; - final reactions = - cleanedChannelStates.expand((it) => it.messages).expand((it) => [ + final reactions = cleanedChannelStates + .expand((it) => it.messages) + .expand((it) => [ if (it.ownReactions != null) ...it.ownReactions!.where((r) => r.userId != null), if (it.latestReactions != null) ...it.latestReactions!.where((r) => r.userId != null), - ]); + ]) + .withNullifyer; final users = cleanedChannelStates .map((cs) => [ @@ -220,7 +221,7 @@ abstract class ChatPersistenceClient { ...cs.members.map((m) => m.user), ]) .expand((it) => it) - .where((it) => it != null) as Iterable; + .withNullifyer; final updateMessagesFuture = cleanedChannelStates.map((it) { final cid = it.channel!.cid; diff --git a/packages/stream_chat/lib/src/extensions/iterable_extension.dart b/packages/stream_chat/lib/src/extensions/iterable_extension.dart new file mode 100644 index 00000000..a7d30f76 --- /dev/null +++ b/packages/stream_chat/lib/src/extensions/iterable_extension.dart @@ -0,0 +1,9 @@ +/// Useful extension functions for [Iterable] +extension IterableX on Iterable { + /// Removes all the null values + /// and converts `Iterable` into `Iterable` + Iterable get withNullifyer => [ + for (final item in this) + if (item != null) item + ]; +} diff --git a/packages/stream_chat_persistence/example/lib/main.dart b/packages/stream_chat_persistence/example/lib/main.dart index b356d96b..f61bfed0 100644 --- a/packages/stream_chat_persistence/example/lib/main.dart +++ b/packages/stream_chat_persistence/example/lib/main.dart @@ -50,15 +50,16 @@ Future main() async { /// Example using Stream's Low Level Dart client. class StreamExample extends StatelessWidget { - /// To initialize this example, an instance of [client] and [channel] is required. + /// To initialize this example, an instance of + /// [client] and [channel] is required. const StreamExample({ - Key key, - @required this.client, - @required this.channel, + Key? key, + required this.client, + required this.channel, }) : super(key: key); - /// Instance of [StreamChatClient] we created earlier. This contains information about - /// our application and connection state. + /// Instance of [StreamChatClient] we created earlier. + /// This contains information about our application and connection state. final StreamChatClient client; /// The channel we'd like to observe and participate. @@ -77,28 +78,31 @@ class StreamExample extends StatelessWidget { /// containing the channel name and a [MessageView] displaying recent messages. class HomeScreen extends StatelessWidget { /// [HomeScreen] is constructed using the [Channel] we defined earlier. - const HomeScreen({Key key, @required this.channel}) : super(key: key); + const HomeScreen({ + Key? key, + required this.channel, + }) : super(key: key); /// Channel object containing the [Channel.id] we'd like to observe. final Channel channel; @override Widget build(BuildContext context) { - final messages = channel.state.channelStateStream; + final messages = channel.state!.channelStateStream; return Scaffold( appBar: AppBar( title: Text('Channel: ${channel.id}'), ), body: SafeArea( - child: StreamBuilder( + child: StreamBuilder( stream: messages, builder: ( BuildContext context, - AsyncSnapshot snapshot, + AsyncSnapshot snapshot, ) { if (snapshot.hasData && snapshot.data != null) { return MessageView( - messages: snapshot.data.messages.reversed.toList(), + messages: snapshot.data!.messages.reversed.toList(), channel: channel, ); } else if (snapshot.hasError) { @@ -110,8 +114,8 @@ class HomeScreen extends StatelessWidget { } return const Center( child: SizedBox( - width: 100.0, - height: 100.0, + width: 100, + height: 100, child: CircularProgressIndicator(), ), ); @@ -127,9 +131,9 @@ class HomeScreen extends StatelessWidget { class MessageView extends StatefulWidget { /// Message takes the latest list of messages and the current channel. const MessageView({ - Key key, - @required this.messages, - @required this.channel, + Key? key, + required this.messages, + required this.channel, }) : super(key: key); /// List of messages sent in the given channel. @@ -143,8 +147,8 @@ class MessageView extends StatefulWidget { } class _MessageViewState extends State { - TextEditingController _controller; - ScrollController _scrollController; + late final TextEditingController _controller; + late final ScrollController _scrollController; List get _messages => widget.messages; @@ -182,20 +186,20 @@ class _MessageViewState extends State { reverse: true, itemBuilder: (BuildContext context, int index) { final item = _messages[index]; - if (item.user.id == widget.channel.client.uid) { + if (item.user?.id == widget.channel.client.uid) { return Align( alignment: Alignment.centerRight, child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text(item.text), + padding: const EdgeInsets.all(8), + child: Text(item.text ?? ''), ), ); } else { return Align( alignment: Alignment.centerLeft, child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text(item.text), + padding: const EdgeInsets.all(8), + child: Text(item.text ?? ''), ), ); } @@ -203,7 +207,7 @@ class _MessageViewState extends State { ), ), Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: Row( children: [ Expanded( @@ -251,7 +255,8 @@ class _MessageViewState extends State { } } -/// Helper extension for quickly retrieving the current user id from a [StreamChatClient]. +/// Helper extension for quickly retrieving +/// the current user id from a [StreamChatClient]. extension on StreamChatClient { - String get uid => state.user.id; + String get uid => state.user!.id; } diff --git a/packages/stream_chat_persistence/example/pubspec.yaml b/packages/stream_chat_persistence/example/pubspec.yaml index 7e3a1549..e6c30c94 100644 --- a/packages/stream_chat_persistence/example/pubspec.yaml +++ b/packages/stream_chat_persistence/example/pubspec.yaml @@ -5,7 +5,7 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: