diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index b21acc7a..acc93337 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -42,9 +42,12 @@ breakdown: * `MessageTheme` is now `MessageThemeData` * `UserListViewTheme` is now `UserListViewThemeData` +- Updated core dependency. + 🐞 Fixed -- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the camera is null. +- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the + camera is null. - Fixed date dividers position/alignment in non reversed `MessageListView`. ## 2.1.2 diff --git a/packages/stream_chat_flutter/lib/src/channel_preview.dart b/packages/stream_chat_flutter/lib/src/channel_preview.dart index e01cd008..f3984ab9 100644 --- a/packages/stream_chat_flutter/lib/src/channel_preview.dart +++ b/packages/stream_chat_flutter/lib/src/channel_preview.dart @@ -94,13 +94,13 @@ class ChannelPreview extends StatelessWidget { textStyle: channelPreviewTheme.titleStyle, ), ), - BetterStreamBuilder?>( + BetterStreamBuilder>( stream: channel.state?.membersStream, initialData: channel.state?.members, comparator: const ListEquality().equals, builder: (context, members) { - if (members?.isEmpty == true || - members?.any((Member e) => + if (members.isEmpty || + members.any((Member e) => e.user!.id == channel.client.state.currentUser?.id) != true) { @@ -153,13 +153,10 @@ class ChannelPreview extends StatelessWidget { )); } - Widget _buildDate(BuildContext context) => BetterStreamBuilder( + Widget _buildDate(BuildContext context) => BetterStreamBuilder( stream: channel.lastMessageAtStream, initialData: channel.lastMessageAt, builder: (context, data) { - if (data == null) { - return const Offstage(); - } final lastMessageAt = data.toLocal(); String stringDate; @@ -213,12 +210,12 @@ class ChannelPreview extends StatelessWidget { Widget _buildLastMessage(BuildContext context) => Align( alignment: Alignment.centerLeft, - child: BetterStreamBuilder?>( + child: BetterStreamBuilder>( stream: channel.state!.messagesStream, initialData: channel.state!.messages, builder: (context, data) { - final lastMessage = data - ?.lastWhereOrNull((m) => m.shadowed != true && !m.isDeleted); + final lastMessage = + data.lastWhereOrNull((m) => !m.shadowed && !m.isDeleted); if (lastMessage == null) { return const SizedBox(); } diff --git a/packages/stream_chat_flutter/lib/src/connection_status_builder.dart b/packages/stream_chat_flutter/lib/src/connection_status_builder.dart index fbe7ffae..2cba8eb4 100644 --- a/packages/stream_chat_flutter/lib/src/connection_status_builder.dart +++ b/packages/stream_chat_flutter/lib/src/connection_status_builder.dart @@ -38,7 +38,7 @@ class ConnectionStatusBuilder extends StatelessWidget { return BetterStreamBuilder( initialData: client.wsConnectionStatus, stream: stream, - loadingBuilder: loadingBuilder, + noDataBuilder: loadingBuilder, errorBuilder: (context, error) { if (errorBuilder != null) { return errorBuilder!(context, error); diff --git a/packages/stream_chat_flutter/lib/src/unread_indicator.dart b/packages/stream_chat_flutter/lib/src/unread_indicator.dart index 381bad39..e5f3027b 100644 --- a/packages/stream_chat_flutter/lib/src/unread_indicator.dart +++ b/packages/stream_chat_flutter/lib/src/unread_indicator.dart @@ -17,7 +17,7 @@ class UnreadIndicator extends StatelessWidget { Widget build(BuildContext context) { final client = StreamChat.of(context).client; return IgnorePointer( - child: BetterStreamBuilder( + child: BetterStreamBuilder( stream: cid != null ? client.state.channels[cid]?.state?.unreadCountStream : client.state.totalUnreadCountStream, @@ -25,7 +25,7 @@ class UnreadIndicator extends StatelessWidget { ? client.state.channels[cid]?.state?.unreadCount : client.state.totalUnreadCount, builder: (context, data) { - if (data == null || data == 0) { + if (data == 0) { return const Offstage(); } return Material( diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index 65280674..ad331bc2 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,5 +1,11 @@ ## Upcoming +🛑️ Breaking Changes from `2.1.1` +- Renamed `BetterStreamBuilder.loadingBuilder` to `.noDataBuilder` + +🔄 Changed +- `BetterStreamBuilder.initialData` is now nullable/not-required. + 🐞 Fixed - [#612](https://github.com/GetStream/stream-chat-flutter/issues/612) `ChannelListView` pagination doesn't work after refresh diff --git a/packages/stream_chat_flutter_core/lib/src/better_stream_builder.dart b/packages/stream_chat_flutter_core/lib/src/better_stream_builder.dart index 871a8a1d..3c456246 100644 --- a/packages/stream_chat_flutter_core/lib/src/better_stream_builder.dart +++ b/packages/stream_chat_flutter_core/lib/src/better_stream_builder.dart @@ -6,23 +6,23 @@ import 'package:flutter/widgets.dart'; /// It requires [initialData] and will rebuild /// only when the new data is different than the current data /// The [comparator] is used to check if the new data is different -class BetterStreamBuilder extends StatefulWidget { +class BetterStreamBuilder extends StatefulWidget { /// Creates a new BetterStreamBuilder const BetterStreamBuilder({ required this.stream, - required this.initialData, required this.builder, - this.loadingBuilder, + this.initialData, + this.noDataBuilder, this.errorBuilder, this.comparator, Key? key, }) : super(key: key); /// The stream to listen to - final Stream? stream; + final Stream? stream; /// The initial data available - final T initialData; + final T? initialData; /// Comparator used to check if the new data is different than the last one final bool Function(T?, T?)? comparator; @@ -31,7 +31,7 @@ class BetterStreamBuilder extends StatefulWidget { final Widget Function(BuildContext context, T data) builder; /// Builder that builds when the data is null - final Widget Function(BuildContext context)? loadingBuilder; + final Widget Function(BuildContext context)? noDataBuilder; /// Builder used when there is an error final Widget Function(BuildContext context, Object error)? errorBuilder; @@ -40,21 +40,26 @@ class BetterStreamBuilder extends StatefulWidget { _BetterStreamBuilderState createState() => _BetterStreamBuilderState(); } -class _BetterStreamBuilderState extends State> { +class _BetterStreamBuilderState + extends State> { T? _lastEvent; - StreamSubscription? _subscription; + StreamSubscription? _subscription; Object? _lastError; @override Widget build(BuildContext context) { - if (_lastError != null) { - return widget.errorBuilder!(context, _lastError!); + final error = _lastError; + if (error != null) { + final errorBuilder = widget.errorBuilder; + if (errorBuilder != null) { + return errorBuilder(context, error); + } } - - if (_lastEvent == null) { - return widget.loadingBuilder?.call(context) ?? const Offstage(); + final event = _lastEvent; + if (event == null) { + return widget.noDataBuilder?.call(context) ?? const Offstage(); } - return widget.builder(context, _lastEvent ?? widget.initialData); + return widget.builder(context, event); } @override @@ -87,22 +92,22 @@ class _BetterStreamBuilderState extends State> { void _onError(error) { if (widget.errorBuilder != null && error != _lastError) { + _lastError = error; if (mounted) { setState(() {}); } - _lastError = error; } } - void _onEvent(T event) { + void _onEvent(T? event) { _lastError = null; final isEqual = widget.comparator?.call(_lastEvent, event) ?? event == _lastEvent; if (!isEqual) { + _lastEvent = event; if (mounted) { setState(() {}); } - _lastEvent = event; } } } diff --git a/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart b/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart index c59b2030..c5d3f69a 100644 --- a/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart @@ -4,6 +4,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_flutter_core/src/better_stream_builder.dart'; import 'package:stream_chat_flutter_core/src/channels_bloc.dart'; import 'package:stream_chat_flutter_core/src/stream_chat_core.dart'; import 'package:stream_chat_flutter_core/src/typedef.dart'; @@ -137,19 +138,14 @@ class ChannelListCoreState extends State { @override Widget build(BuildContext context) => _buildListView(_channelsBloc); - StreamBuilder> _buildListView( + BetterStreamBuilder> _buildListView( ChannelsBlocState channelsBlocState, ) => - StreamBuilder>( + BetterStreamBuilder>( stream: channelsBlocState.channelsStream, - builder: (context, snapshot) { - if (snapshot.hasError) { - return widget.errorBuilder(context, snapshot.error!); - } - if (!snapshot.hasData) { - return widget.loadingBuilder(context); - } - final channels = snapshot.data!; + errorBuilder: widget.errorBuilder, + noDataBuilder: widget.loadingBuilder, + builder: (context, channels) { if (channels.isEmpty) { return widget.emptyBuilder(context); } diff --git a/packages/stream_chat_flutter_core/lib/src/message_list_core.dart b/packages/stream_chat_flutter_core/lib/src/message_list_core.dart index d3d69dfb..b9b423ce 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_list_core.dart @@ -138,7 +138,7 @@ class MessageListCoreState extends State { return true; } - return BetterStreamBuilder?>( + return BetterStreamBuilder>( initialData: initialData, comparator: const ListEquality().equals, stream: messagesStream!.map( @@ -148,9 +148,9 @@ class MessageListCoreState extends State { ), ), errorBuilder: widget.errorBuilder, - loadingBuilder: widget.loadingBuilder, + noDataBuilder: widget.loadingBuilder, builder: (context, data) { - final messageList = data?.reversed.toList(growable: false) ?? []; + final messageList = data.reversed.toList(growable: false); if (messageList.isEmpty && !_isThreadConversation) { if (_upToDate) { return widget.emptyBuilder(context); diff --git a/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart b/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart index 4901c332..234b5c9a 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_flutter_core/src/better_stream_builder.dart'; import 'package:stream_chat_flutter_core/src/message_search_bloc.dart'; import 'package:stream_chat_flutter_core/src/typedef.dart'; @@ -132,16 +133,11 @@ class MessageSearchListCoreState extends State { Widget build(BuildContext context) => _buildListView(_messageSearchBloc!); Widget _buildListView(MessageSearchBlocState messageSearchBloc) => - StreamBuilder>( + BetterStreamBuilder>( stream: messageSearchBloc.messagesStream, - builder: (context, snapshot) { - if (snapshot.hasError) { - return widget.errorBuilder(context, snapshot.error!); - } - if (!snapshot.hasData) { - return widget.loadingBuilder(context); - } - final items = snapshot.data!; + errorBuilder: widget.errorBuilder, + noDataBuilder: widget.loadingBuilder, + builder: (context, items) { if (items.isEmpty) { return widget.emptyBuilder(context); } diff --git a/packages/stream_chat_flutter_core/lib/src/user_list_core.dart b/packages/stream_chat_flutter_core/lib/src/user_list_core.dart index a45aa904..57d61fe6 100644 --- a/packages/stream_chat_flutter_core/lib/src/user_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/user_list_core.dart @@ -176,16 +176,11 @@ class UserListCoreState extends State }, ); - StreamBuilder> _buildListView() => StreamBuilder( + BetterStreamBuilder> _buildListView() => BetterStreamBuilder( stream: _buildUserStream(), - builder: (context, snapshot) { - if (snapshot.hasError) { - return widget.errorBuilder(context, snapshot.error!); - } - if (!snapshot.hasData) { - return widget.loadingBuilder(context); - } - final items = snapshot.data!; + errorBuilder: widget.errorBuilder, + noDataBuilder: widget.loadingBuilder, + builder: (context, items) { if (items.isEmpty) { return widget.emptyBuilder(context); }