Merge branch 'master' into feat/custom-attachment-upload
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
- [Register](https://getstream.io/chat/trial/) to get an API key for Stream Chat
|
- [Register](https://getstream.io/chat/trial/) to get an API key for Stream Chat
|
||||||
- [Flutter Chat Tutorial](https://getstream.io/chat/flutter/tutorial/)
|
- [Flutter Chat Tutorial](https://getstream.io/chat/flutter/tutorial/)
|
||||||
- [Chat UI Kit](https://getstream.io/chat/ui-kit/)
|
- [Chat UI Kit](https://getstream.io/chat/ui-kit/)
|
||||||
|
- [Sample apps](https://github.com/GetStream/flutter-samples)
|
||||||
|
|
||||||
This repository contains code for our [Dart](https://dart.dev/) and [Flutter](https://flutter.dev/) chat clients.
|
This repository contains code for our [Dart](https://dart.dev/) and [Flutter](https://flutter.dev/) chat clients.
|
||||||
|
|
||||||
|
|||||||
@@ -67,8 +67,6 @@ class ChannelListView extends StatefulWidget {
|
|||||||
this.channelWidget,
|
this.channelWidget,
|
||||||
this.channelPreviewBuilder,
|
this.channelPreviewBuilder,
|
||||||
this.separatorBuilder,
|
this.separatorBuilder,
|
||||||
this.errorBuilder,
|
|
||||||
this.emptyBuilder,
|
|
||||||
this.onImageTap,
|
this.onImageTap,
|
||||||
this.onStartChatPressed,
|
this.onStartChatPressed,
|
||||||
this.swipeToAction = false,
|
this.swipeToAction = false,
|
||||||
@@ -77,17 +75,15 @@ class ChannelListView extends StatefulWidget {
|
|||||||
this.padding,
|
this.padding,
|
||||||
this.selectedChannels = const [],
|
this.selectedChannels = const [],
|
||||||
this.onViewInfoTap,
|
this.onViewInfoTap,
|
||||||
|
this.errorBuilder,
|
||||||
|
this.emptyBuilder,
|
||||||
|
this.loadingBuilder,
|
||||||
|
this.listBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// The builder that will be used in case of error
|
|
||||||
final Widget Function(Error error) errorBuilder;
|
|
||||||
|
|
||||||
/// If true a default swipe to action behaviour will be added to this widget
|
/// If true a default swipe to action behaviour will be added to this widget
|
||||||
final bool swipeToAction;
|
final bool swipeToAction;
|
||||||
|
|
||||||
/// The builder used when the channel list is empty.
|
|
||||||
final WidgetBuilder emptyBuilder;
|
|
||||||
|
|
||||||
/// The query filters to use.
|
/// The query filters to use.
|
||||||
/// You can query on any of the custom fields you've defined on the [Channel].
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
/// You can also filter other built-in channel fields.
|
/// You can also filter other built-in channel fields.
|
||||||
@@ -147,6 +143,18 @@ class ChannelListView extends StatefulWidget {
|
|||||||
|
|
||||||
final ViewInfoCallback onViewInfoTap;
|
final ViewInfoCallback onViewInfoTap;
|
||||||
|
|
||||||
|
/// The builder that will be used in case of error
|
||||||
|
final ErrorBuilder errorBuilder;
|
||||||
|
|
||||||
|
/// The builder that will be used in case of loading
|
||||||
|
final WidgetBuilder loadingBuilder;
|
||||||
|
|
||||||
|
/// The builder which is used when list of channels loads
|
||||||
|
final Function(BuildContext, List<Channel>) listBuilder;
|
||||||
|
|
||||||
|
/// The builder used when the channel list is empty.
|
||||||
|
final WidgetBuilder emptyBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ChannelListViewState createState() => _ChannelListViewState();
|
_ChannelListViewState createState() => _ChannelListViewState();
|
||||||
}
|
}
|
||||||
@@ -161,18 +169,22 @@ class _ChannelListViewState extends State<ChannelListView>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var child = ChannelListCore(
|
var child = ChannelListCore(
|
||||||
channelListController: _channelListController,
|
channelListController: _channelListController,
|
||||||
listBuilder: (context, list) {
|
listBuilder: widget.listBuilder ??
|
||||||
return _buildListView(list);
|
(context, list) {
|
||||||
},
|
return _buildListView(list);
|
||||||
emptyBuilder: (BuildContext context) {
|
},
|
||||||
return _buildEmptyWidget();
|
emptyBuilder: widget.emptyBuilder ??
|
||||||
},
|
(BuildContext context) {
|
||||||
errorBuilder: (BuildContext context, dynamic error) {
|
return _buildEmptyWidget();
|
||||||
return _buildErrorWidget(context);
|
},
|
||||||
},
|
errorBuilder: widget.errorBuilder ??
|
||||||
loadingBuilder: (BuildContext context) {
|
(BuildContext context, dynamic error) {
|
||||||
return _buildLoadingWidget();
|
return _buildErrorWidget(context);
|
||||||
},
|
},
|
||||||
|
loadingBuilder: widget.loadingBuilder ??
|
||||||
|
(BuildContext context) {
|
||||||
|
return _buildLoadingWidget();
|
||||||
|
},
|
||||||
pagination: widget.pagination,
|
pagination: widget.pagination,
|
||||||
options: widget.options,
|
options: widget.options,
|
||||||
sort: widget.sort,
|
sort: widget.sort,
|
||||||
@@ -236,10 +248,6 @@ class _ChannelListViewState extends State<ChannelListView>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEmptyWidget() {
|
Widget _buildEmptyWidget() {
|
||||||
if (widget.emptyBuilder != null) {
|
|
||||||
return widget.emptyBuilder(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, viewportConstraints) {
|
builder: (context, viewportConstraints) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
|||||||
@@ -126,6 +126,10 @@ class MessageListView extends StatefulWidget {
|
|||||||
this.messageHighlightColor,
|
this.messageHighlightColor,
|
||||||
this.onShowMessage,
|
this.onShowMessage,
|
||||||
this.showConnectionStateTile = false,
|
this.showConnectionStateTile = false,
|
||||||
|
this.loadingBuilder,
|
||||||
|
this.emptyBuilder,
|
||||||
|
this.messageListBuilder,
|
||||||
|
this.errorWidgetBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Function used to build a custom message widget
|
/// Function used to build a custom message widget
|
||||||
@@ -185,6 +189,20 @@ class MessageListView extends StatefulWidget {
|
|||||||
|
|
||||||
final bool showConnectionStateTile;
|
final bool showConnectionStateTile;
|
||||||
|
|
||||||
|
/// Function called when messages are fetched
|
||||||
|
final Widget Function(BuildContext, List<Message>) messageListBuilder;
|
||||||
|
|
||||||
|
/// Function used to build a loading widget
|
||||||
|
final WidgetBuilder loadingBuilder;
|
||||||
|
|
||||||
|
/// Function used to build an empty widget
|
||||||
|
final WidgetBuilder emptyBuilder;
|
||||||
|
|
||||||
|
/// Callback triggered when an error occurs while performing the given request.
|
||||||
|
/// This parameter can be used to display an error message to users in the event
|
||||||
|
/// of a connection failure.
|
||||||
|
final ErrorBuilder errorWidgetBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MessageListViewState createState() => _MessageListViewState();
|
_MessageListViewState createState() => _MessageListViewState();
|
||||||
}
|
}
|
||||||
@@ -242,41 +260,45 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MessageListCore(
|
return MessageListCore(
|
||||||
loadingBuilder: (context) {
|
loadingBuilder: widget.loadingBuilder ??
|
||||||
return Center(
|
(context) {
|
||||||
child: const CircularProgressIndicator(),
|
return Center(
|
||||||
);
|
child: const CircularProgressIndicator(),
|
||||||
},
|
);
|
||||||
emptyBuilder: (context) {
|
},
|
||||||
return Center(
|
emptyBuilder: widget.emptyBuilder ??
|
||||||
child: Text(
|
(context) {
|
||||||
'No chats here yet...',
|
return Center(
|
||||||
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
child: Text(
|
||||||
color: StreamChatTheme.of(context)
|
'No chats here yet...',
|
||||||
.colorTheme
|
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
||||||
.black
|
color: StreamChatTheme.of(context)
|
||||||
.withOpacity(.5)),
|
.colorTheme
|
||||||
),
|
.black
|
||||||
);
|
.withOpacity(.5)),
|
||||||
},
|
),
|
||||||
messageListBuilder: (context, list) {
|
);
|
||||||
return _buildListView(list);
|
},
|
||||||
},
|
messageListBuilder: widget.messageListBuilder ??
|
||||||
|
(context, list) {
|
||||||
|
return _buildListView(list);
|
||||||
|
},
|
||||||
messageListController: _messageListController,
|
messageListController: _messageListController,
|
||||||
parentMessage: widget.parentMessage,
|
parentMessage: widget.parentMessage,
|
||||||
showScrollToBottom: widget.showScrollToBottom,
|
showScrollToBottom: widget.showScrollToBottom,
|
||||||
errorWidgetBuilder: (BuildContext context, Object error) {
|
errorWidgetBuilder: widget.errorWidgetBuilder ??
|
||||||
return Center(
|
(BuildContext context, Object error) {
|
||||||
child: Text(
|
return Center(
|
||||||
'Something went wrong',
|
child: Text(
|
||||||
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
'Something went wrong',
|
||||||
color: StreamChatTheme.of(context)
|
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
||||||
.colorTheme
|
color: StreamChatTheme.of(context)
|
||||||
.black
|
.colorTheme
|
||||||
.withOpacity(.5)),
|
.black
|
||||||
),
|
.withOpacity(.5)),
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,14 +53,16 @@ class MessageSearchListView extends StatefulWidget {
|
|||||||
this.sortOptions,
|
this.sortOptions,
|
||||||
this.paginationParams,
|
this.paginationParams,
|
||||||
this.messageFilters,
|
this.messageFilters,
|
||||||
this.emptyBuilder,
|
|
||||||
this.errorBuilder,
|
|
||||||
this.separatorBuilder,
|
this.separatorBuilder,
|
||||||
this.itemBuilder,
|
this.itemBuilder,
|
||||||
this.onItemTap,
|
this.onItemTap,
|
||||||
this.showResultCount = true,
|
this.showResultCount = true,
|
||||||
this.pullToRefresh = true,
|
this.pullToRefresh = true,
|
||||||
this.showErrorTile = false,
|
this.showErrorTile = false,
|
||||||
|
this.emptyBuilder,
|
||||||
|
this.errorBuilder,
|
||||||
|
this.loadingBuilder,
|
||||||
|
this.childBuilder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Message String to search on
|
/// Message String to search on
|
||||||
@@ -94,12 +96,6 @@ class MessageSearchListView extends StatefulWidget {
|
|||||||
/// Function called when tapping on a [MessageSearchItem]
|
/// Function called when tapping on a [MessageSearchItem]
|
||||||
final MessageSearchItemTapCallback onItemTap;
|
final MessageSearchItemTapCallback onItemTap;
|
||||||
|
|
||||||
/// The builder used when the channel list is empty.
|
|
||||||
final EmptyMessageSearchBuilder emptyBuilder;
|
|
||||||
|
|
||||||
/// The builder that will be used in case of error
|
|
||||||
final Widget Function(Error error) errorBuilder;
|
|
||||||
|
|
||||||
/// Builder used to create a custom item separator
|
/// Builder used to create a custom item separator
|
||||||
final IndexedWidgetBuilder separatorBuilder;
|
final IndexedWidgetBuilder separatorBuilder;
|
||||||
|
|
||||||
@@ -111,6 +107,18 @@ class MessageSearchListView extends StatefulWidget {
|
|||||||
|
|
||||||
final bool showErrorTile;
|
final bool showErrorTile;
|
||||||
|
|
||||||
|
/// The builder that is used when the search messages are fetched
|
||||||
|
final Widget Function(List<GetMessageResponse>) childBuilder;
|
||||||
|
|
||||||
|
/// The builder used when the channel list is empty.
|
||||||
|
final WidgetBuilder emptyBuilder;
|
||||||
|
|
||||||
|
/// The builder that will be used in case of error
|
||||||
|
final ErrorBuilder errorBuilder;
|
||||||
|
|
||||||
|
/// The builder that will be used in case of loading
|
||||||
|
final WidgetBuilder loadingBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MessageSearchListViewState createState() => _MessageSearchListViewState();
|
_MessageSearchListViewState createState() => _MessageSearchListViewState();
|
||||||
}
|
}
|
||||||
@@ -128,101 +136,98 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
|
|||||||
paginationParams: widget.paginationParams,
|
paginationParams: widget.paginationParams,
|
||||||
messageFilters: widget.messageFilters,
|
messageFilters: widget.messageFilters,
|
||||||
messageSearchListController: _messageSearchListController,
|
messageSearchListController: _messageSearchListController,
|
||||||
emptyBuilder: (context) {
|
emptyBuilder: widget.emptyBuilder ??
|
||||||
if (widget.emptyBuilder != null) {
|
(context) {
|
||||||
return widget.emptyBuilder(context, widget.messageQuery);
|
return LayoutBuilder(
|
||||||
}
|
builder: (context, viewportConstraints) {
|
||||||
return LayoutBuilder(
|
return SingleChildScrollView(
|
||||||
builder: (context, viewportConstraints) {
|
physics: AlwaysScrollableScrollPhysics(),
|
||||||
return SingleChildScrollView(
|
child: ConstrainedBox(
|
||||||
physics: AlwaysScrollableScrollPhysics(),
|
constraints: BoxConstraints(
|
||||||
child: ConstrainedBox(
|
minHeight: viewportConstraints.maxHeight,
|
||||||
constraints: BoxConstraints(
|
),
|
||||||
minHeight: viewportConstraints.maxHeight,
|
child: Center(
|
||||||
),
|
child: Text('There are no messages currently'),
|
||||||
child: Center(
|
),
|
||||||
child: Text('There are no messages currently'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
errorBuilder: (BuildContext context, dynamic error) {
|
|
||||||
if (error is Error) {
|
|
||||||
print((error).stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (widget.errorBuilder != null) {
|
|
||||||
return widget.errorBuilder(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = error.toString();
|
|
||||||
if (error is DioError) {
|
|
||||||
if (error.type == DioErrorType.RESPONSE) {
|
|
||||||
message = error.message;
|
|
||||||
} else {
|
|
||||||
message = 'Check your connection and retry';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return InfoTile(
|
|
||||||
showMessage: widget.showErrorTile,
|
|
||||||
tileAnchor: Alignment.topCenter,
|
|
||||||
childAnchor: Alignment.topCenter,
|
|
||||||
message: 'An error occurred.',
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
WidgetSpan(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 2.0),
|
|
||||||
child: Icon(Icons.error_outline),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(text: 'Error loading messages'),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
style: Theme.of(context).textTheme.headline6,
|
);
|
||||||
),
|
},
|
||||||
Padding(
|
);
|
||||||
padding: const EdgeInsets.only(top: 16.0),
|
},
|
||||||
child: Text(message),
|
errorBuilder: widget.emptyBuilder ??
|
||||||
),
|
(BuildContext context, dynamic error) {
|
||||||
RaisedButton(
|
if (error is Error) {
|
||||||
onPressed: () {
|
print((error).stackTrace);
|
||||||
_messageSearchListController.loadData();
|
}
|
||||||
},
|
|
||||||
child: Text('Retry'),
|
var message = error.toString();
|
||||||
),
|
if (error is DioError) {
|
||||||
],
|
if (error.type == DioErrorType.RESPONSE) {
|
||||||
),
|
message = error.message;
|
||||||
),
|
} else {
|
||||||
);
|
message = 'Check your connection and retry';
|
||||||
},
|
}
|
||||||
loadingBuilder: (context) {
|
}
|
||||||
return LayoutBuilder(
|
return InfoTile(
|
||||||
builder: (context, viewportConstraints) {
|
showMessage: widget.showErrorTile,
|
||||||
return SingleChildScrollView(
|
tileAnchor: Alignment.topCenter,
|
||||||
physics: AlwaysScrollableScrollPhysics(),
|
childAnchor: Alignment.topCenter,
|
||||||
child: ConstrainedBox(
|
message: 'An error occurred.',
|
||||||
constraints: BoxConstraints(
|
child: Center(
|
||||||
minHeight: viewportConstraints.maxHeight,
|
child: Column(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
child: Center(
|
children: <Widget>[
|
||||||
child: CircularProgressIndicator(),
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
WidgetSpan(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 2.0),
|
||||||
|
child: Icon(Icons.error_outline),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(text: 'Error loading messages'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style: Theme.of(context).textTheme.headline6,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
child: Text(message),
|
||||||
|
),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () {
|
||||||
|
_messageSearchListController.loadData();
|
||||||
|
},
|
||||||
|
child: Text('Retry'),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
loadingBuilder: widget.loadingBuilder ??
|
||||||
},
|
(context) {
|
||||||
childBuilder: (list) {
|
return LayoutBuilder(
|
||||||
return _buildListView(list);
|
builder: (context, viewportConstraints) {
|
||||||
},
|
return SingleChildScrollView(
|
||||||
|
physics: AlwaysScrollableScrollPhysics(),
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: viewportConstraints.maxHeight,
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
childBuilder: widget.childBuilder ??
|
||||||
|
(list) {
|
||||||
|
return _buildListView(list);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ class UserListView extends StatefulWidget {
|
|||||||
/// Instantiate a new UserListView
|
/// Instantiate a new UserListView
|
||||||
const UserListView({
|
const UserListView({
|
||||||
Key key,
|
Key key,
|
||||||
this.errorBuilder,
|
|
||||||
this.emptyBuilder,
|
|
||||||
this.filter,
|
this.filter,
|
||||||
this.options,
|
this.options,
|
||||||
this.sort,
|
this.sort,
|
||||||
@@ -61,18 +59,16 @@ class UserListView extends StatefulWidget {
|
|||||||
this.pullToRefresh = true,
|
this.pullToRefresh = true,
|
||||||
this.groupAlphabetically = false,
|
this.groupAlphabetically = false,
|
||||||
this.crossAxisCount = 1,
|
this.crossAxisCount = 1,
|
||||||
|
this.errorBuilder,
|
||||||
|
this.emptyBuilder,
|
||||||
|
this.loadingBuilder,
|
||||||
|
this.listBuilder,
|
||||||
}) : assert(
|
}) : assert(
|
||||||
crossAxisCount == 1 || groupAlphabetically == false,
|
crossAxisCount == 1 || groupAlphabetically == false,
|
||||||
'Cannot group alphabetically when crossAxisCount > 1',
|
'Cannot group alphabetically when crossAxisCount > 1',
|
||||||
),
|
),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
/// The builder that will be used in case of error
|
|
||||||
final Widget Function(Error error) errorBuilder;
|
|
||||||
|
|
||||||
/// The builder used when the channel list is empty.
|
|
||||||
final WidgetBuilder emptyBuilder;
|
|
||||||
|
|
||||||
/// The query filters to use.
|
/// The query filters to use.
|
||||||
/// You can query on any of the custom fields you've defined on the [Channel].
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
/// You can also filter other built-in channel fields.
|
/// You can also filter other built-in channel fields.
|
||||||
@@ -130,6 +126,18 @@ class UserListView extends StatefulWidget {
|
|||||||
/// The number of children in the cross axis.
|
/// The number of children in the cross axis.
|
||||||
final int crossAxisCount;
|
final int crossAxisCount;
|
||||||
|
|
||||||
|
/// The builder that will be used in case of error
|
||||||
|
final Widget Function(Error error) errorBuilder;
|
||||||
|
|
||||||
|
/// The builder that will be used to build the list
|
||||||
|
final Widget Function(BuildContext context, List<ListItem> users) listBuilder;
|
||||||
|
|
||||||
|
/// The builder that will be used for loading
|
||||||
|
final WidgetBuilder loadingBuilder;
|
||||||
|
|
||||||
|
/// The builder used when the channel list is empty.
|
||||||
|
final WidgetBuilder emptyBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_UserListViewState createState() => _UserListViewState();
|
_UserListViewState createState() => _UserListViewState();
|
||||||
}
|
}
|
||||||
@@ -143,32 +151,36 @@ class _UserListViewState extends State<UserListView>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var child = UserListCore(
|
var child = UserListCore(
|
||||||
errorBuilder: (err) {
|
errorBuilder: widget.errorBuilder ??
|
||||||
return _buildError(err);
|
(err) {
|
||||||
},
|
return _buildError(err);
|
||||||
emptyBuilder: (context) {
|
},
|
||||||
return _buildEmpty();
|
emptyBuilder: widget.emptyBuilder ??
|
||||||
},
|
(context) {
|
||||||
loadingBuilder: (context) {
|
return _buildEmpty();
|
||||||
return LayoutBuilder(
|
},
|
||||||
builder: (context, viewportConstraints) {
|
loadingBuilder: widget.loadingBuilder ??
|
||||||
return SingleChildScrollView(
|
(context) {
|
||||||
physics: AlwaysScrollableScrollPhysics(),
|
return LayoutBuilder(
|
||||||
child: ConstrainedBox(
|
builder: (context, viewportConstraints) {
|
||||||
constraints: BoxConstraints(
|
return SingleChildScrollView(
|
||||||
minHeight: viewportConstraints.maxHeight,
|
physics: AlwaysScrollableScrollPhysics(),
|
||||||
),
|
child: ConstrainedBox(
|
||||||
child: Center(
|
constraints: BoxConstraints(
|
||||||
child: CircularProgressIndicator(),
|
minHeight: viewportConstraints.maxHeight,
|
||||||
),
|
),
|
||||||
),
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
listBuilder: widget.listBuilder ??
|
||||||
},
|
(context, list) {
|
||||||
listBuilder: (context, list) {
|
return _buildListView(list);
|
||||||
return _buildListView(list);
|
},
|
||||||
},
|
|
||||||
pagination: widget.pagination,
|
pagination: widget.pagination,
|
||||||
options: widget.options,
|
options: widget.options,
|
||||||
sort: widget.sort,
|
sort: widget.sort,
|
||||||
@@ -195,10 +207,6 @@ class _UserListViewState extends State<UserListView>
|
|||||||
Widget _buildError(Error error) {
|
Widget _buildError(Error error) {
|
||||||
print((error).stackTrace);
|
print((error).stackTrace);
|
||||||
|
|
||||||
if (widget.errorBuilder != null) {
|
|
||||||
return widget.errorBuilder(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = error.toString();
|
var message = error.toString();
|
||||||
if (error is DioError) {
|
if (error is DioError) {
|
||||||
final dioError = error as DioError;
|
final dioError = error as DioError;
|
||||||
@@ -246,10 +254,6 @@ class _UserListViewState extends State<UserListView>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEmpty() {
|
Widget _buildEmpty() {
|
||||||
if (widget.emptyBuilder != null) {
|
|
||||||
return widget.emptyBuilder(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, viewportConstraints) {
|
builder: (context, viewportConstraints) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
|||||||
Reference in New Issue
Block a user