From 7cbdb3bde07be9b4f619683343ad2b548fbe930e Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 6 Sep 2023 21:50:27 +0530 Subject: [PATCH] feat(core): add support for `StreamChannel.loadingBuilder` and `.errorBuilder`. Signed-off-by: Sahil Kumar --- .../stream_chat_flutter_core/CHANGELOG.md | 14 +++-- .../lib/src/stream_channel.dart | 52 ++++++++++++++----- .../lib/src/typedef.dart | 1 + 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index aae7bb18b..8f0395324 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,3 +1,8 @@ +## Upcoming + +- Added support for `StreamChannel.loadingBuilder` and `StreamChannel.errorBuilder` to customize + loading and error states. + ## 6.8.0 - Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 @@ -35,9 +40,11 @@ - Updated `dart` sdk environment range to support `3.0.0`. - Updated `stream_chat` dependency to [`6.1.0`](https://pub.dev/packages/stream_chat/changelog). -- [[#1356]](https://github.com/GetStream/stream-chat-flutter/issues/1356) Channel doesn't auto display again after being +- [[#1356]](https://github.com/GetStream/stream-chat-flutter/issues/1356) Channel doesn't auto + display again after being hidden. -- [[#1540]](https://github.com/GetStream/stream-chat-flutter/issues/1540) Use `CircularProgressIndicator.adaptive` +- [[#1540]](https://github.com/GetStream/stream-chat-flutter/issues/1540) + Use `CircularProgressIndicator.adaptive` instead of material indicator. ## 6.0.0 @@ -56,7 +63,8 @@ ## 5.1.0 -- Deprecated the `sort` parameter in the `StreamChannelListController` in favor of `channelStateSort`. +- Deprecated the `sort` parameter in the `StreamChannelListController` in favor + of `channelStateSort`. ## 5.0.0 diff --git a/packages/stream_chat_flutter_core/lib/src/stream_channel.dart b/packages/stream_chat_flutter_core/lib/src/stream_channel.dart index 5bb8dee7f..095bbec93 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_channel.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_channel.dart @@ -15,6 +15,15 @@ enum QueryDirection { bottom, } +/// Signature used by [StreamChannel.errorBuilder] to create a replacement +/// widget for an error that occurs while asynchronously building the channel. +// TODO: Remove once ErrorBuilder supports passing stacktrace. +typedef ErrorWidgetBuilder = Widget Function( + BuildContext context, + Object error, + StackTrace? stackTrace, +); + /// Widget used to provide information about the channel to the widget tree /// /// Use [StreamChannel.of] to get the current [StreamChannelState] instance. @@ -27,6 +36,8 @@ class StreamChannel extends StatefulWidget { required this.channel, this.showLoading = true, this.initialMessageId, + this.errorBuilder = _defaultErrorBuilder, + this.loadingBuilder = _defaultLoadingBuilder, }); /// The child of the widget @@ -41,6 +52,31 @@ class StreamChannel extends StatefulWidget { /// If passed the channel will load from this particular message. final String? initialMessageId; + /// Widget builder used in case the channel is initialising. + final WidgetBuilder loadingBuilder; + + /// Widget builder used in case an error occurs while building the channel. + final ErrorWidgetBuilder errorBuilder; + + static Widget _defaultLoadingBuilder(BuildContext context) { + return const Center(child: CircularProgressIndicator.adaptive()); + } + + static Widget _defaultErrorBuilder( + BuildContext context, + Object error, + StackTrace? stackTrace, + ) { + if (error is DioException) { + if (error.type == DioExceptionType.badResponse) { + return Center(child: Text(error.message ?? 'Bad response')); + } + return const Center(child: Text('Check your connection and retry')); + } + + return Center(child: Text(error.toString())); + } + /// Use this method to get the current [StreamChannelState] instance static StreamChannelState of(BuildContext context) { StreamChannelState? streamChannelState; @@ -430,22 +466,14 @@ class StreamChannelState extends State { ], builder: (context, snapshot) { if (snapshot.hasError) { - final error = snapshot.error; - if (error is DioException) { - if (error.type == DioExceptionType.badResponse) { - return Center(child: Text(error.message ?? 'Bad response')); - } - return const Center(child: Text('Check your connection and retry')); - } - - return Center(child: Text(error.toString())); + final error = snapshot.error!; + final stackTrace = snapshot.stackTrace; + return widget.errorBuilder(context, error, stackTrace); } final dataLoaded = snapshot.data?.every((it) => it) == true; if (widget.showLoading && !dataLoaded) { - return const Center( - child: CircularProgressIndicator.adaptive(), - ); + return widget.loadingBuilder(context); } return widget.child; }, diff --git a/packages/stream_chat_flutter_core/lib/src/typedef.dart b/packages/stream_chat_flutter_core/lib/src/typedef.dart index ace8d7e6a..4b69c79c5 100644 --- a/packages/stream_chat_flutter_core/lib/src/typedef.dart +++ b/packages/stream_chat_flutter_core/lib/src/typedef.dart @@ -4,6 +4,7 @@ import 'package:stream_chat/stream_chat.dart'; /// A signature for a callback which exposes an error and returns a function. /// This Callback can be used in cases where an API failure occurs and the /// widget is unable to render data. +// TODO: Add stacktrace as a parameter in v7.0.0 typedef ErrorBuilder = Widget Function(BuildContext context, Object error); /// A Signature for a handler function which will expose a [event].