refactor(ui): add channel list empty and error state widgets.
Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import 'package:stream_chat/stream_chat.dart' hide Success;
|
import 'package:stream_chat/stream_chat.dart' show ChannelState, Event;
|
||||||
import 'package:stream_chat_flutter/src/v4/channel_list_view/stream_channel_list_controller.dart';
|
import 'package:stream_chat_flutter/src/v4/channel_list_view/stream_channel_list_controller.dart';
|
||||||
|
|
||||||
/// Contains handlers that are called from [StreamChannelListController] for
|
/// Contains handlers that are called from [StreamChannelListController] for
|
||||||
|
|||||||
+102
-4
@@ -250,7 +250,12 @@ class _StreamChannelListViewState extends State<StreamChannelListView> {
|
|||||||
builder: (context, value, _) => value.when(
|
builder: (context, value, _) => value.when(
|
||||||
(channels, nextPageKey, error) {
|
(channels, nextPageKey, error) {
|
||||||
if (channels.isEmpty) {
|
if (channels.isEmpty) {
|
||||||
return const Center(child: Text('No channels'));
|
return const Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: StreamChannelListEmpty(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
@@ -321,7 +326,11 @@ class _StreamChannelListViewState extends State<StreamChannelListView> {
|
|||||||
separatorBuilder: widget.separatorBuilder,
|
separatorBuilder: widget.separatorBuilder,
|
||||||
itemBuilder: (_, __) => const StreamChannelListLoadingTile(),
|
itemBuilder: (_, __) => const StreamChannelListLoadingTile(),
|
||||||
),
|
),
|
||||||
error: (error) => Center(child: Text('Error: $error')),
|
error: (error) => Center(
|
||||||
|
child: StreamChannelListError(
|
||||||
|
onPressed: _controller.refresh,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -347,11 +356,11 @@ class ChannelListLoadMoreError extends StatelessWidget {
|
|||||||
/// Creates a new instance of [ChannelListLoadMoreError].
|
/// Creates a new instance of [ChannelListLoadMoreError].
|
||||||
const ChannelListLoadMoreError({
|
const ChannelListLoadMoreError({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.onTap,
|
this.onTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// The callback to invoke when the user taps on the error indicator.
|
/// The callback to invoke when the user taps on the error indicator.
|
||||||
final GestureTapCallback onTap;
|
final GestureTapCallback? onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -395,3 +404,92 @@ class StreamChannelListSeparator extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A widget that is used to display an error screen
|
||||||
|
/// when [StreamChannelListController] fails to load initial channels.
|
||||||
|
class StreamChannelListError extends StatelessWidget {
|
||||||
|
/// Creates a new instance of [StreamChannelListError] widget.
|
||||||
|
const StreamChannelListError({
|
||||||
|
Key? key,
|
||||||
|
this.onPressed,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The callback to invoke when the user taps on the retry button.
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
const WidgetSpan(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(right: 2),
|
||||||
|
child: Icon(Icons.error_outline),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(text: context.translations.loadingChannelsError),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(context.translations.retryLabel),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A widget that is used to display an empty state when
|
||||||
|
/// [StreamChannelListController] loads zero channels.
|
||||||
|
class StreamChannelListEmpty extends StatelessWidget {
|
||||||
|
/// Creates a new instance of [StreamChannelListEmpty] widget.
|
||||||
|
const StreamChannelListEmpty({
|
||||||
|
Key? key,
|
||||||
|
this.onPressed,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// The callback to invoke when the user taps on the start a chat button.
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final chatThemeData = StreamChatTheme.of(context);
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Spacer(),
|
||||||
|
StreamSvgIcon.message(
|
||||||
|
size: 148,
|
||||||
|
color: chatThemeData.colorTheme.disabled,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 28),
|
||||||
|
Text(
|
||||||
|
context.translations.letsStartChattingLabel,
|
||||||
|
style: chatThemeData.textTheme.headline,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
context.translations.sendingFirstMessageLabel,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: chatThemeData.textTheme.body.copyWith(
|
||||||
|
color: chatThemeData.colorTheme.textLowEmphasis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
TextButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(
|
||||||
|
context.translations.startAChatLabel,
|
||||||
|
style: chatThemeData.textTheme.bodyBold.copyWith(
|
||||||
|
color: chatThemeData.colorTheme.accentPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user