fix analysis and update examples

This commit is contained in:
Salvatore Giordano
2022-02-01 10:52:59 +01:00
parent d959131bbd
commit f53ee0b4f1
15 changed files with 223 additions and 164 deletions
@@ -84,7 +84,7 @@ class _SplitViewState extends State<SplitView> {
); );
} }
class ChannelListPage extends StatelessWidget { class ChannelListPage extends StatefulWidget {
const ChannelListPage({ const ChannelListPage({
Key? key, Key? key,
this.onTap, this.onTap,
@@ -92,22 +92,26 @@ class ChannelListPage extends StatelessWidget {
final void Function(Channel)? onTap; final void Function(Channel)? onTap;
@override
State<ChannelListPage> createState() => _ChannelListPageState();
}
class _ChannelListPageState extends State<ChannelListPage> {
late final _listController = StreamChannelListController(
client: StreamChat.of(context).client,
filter: Filter.in_(
'members',
[StreamChat.of(context).currentUser!.id],
),
sort: const [SortOption('last_message_at')],
limit: 20,
);
@override @override
Widget build(BuildContext context) => Scaffold( Widget build(BuildContext context) => Scaffold(
body: ChannelsBloc( body: StreamChannelListView(
child: ChannelListView( onChannelTap: widget.onTap,
onChannelTap: onTap != null controller: _listController,
? (channel, _) {
onTap!(channel);
}
: null,
filter: Filter.in_(
'members',
[StreamChat.of(context).currentUser!.id],
),
sort: const [SortOption('last_message_at')],
limit: 20,
),
), ),
); );
} }
@@ -90,18 +90,15 @@ class ChannelPage extends StatelessWidget {
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies Widget build(BuildContext context) => Scaffold(
Widget build(BuildContext context) { appBar: const ChannelHeader(),
return Scaffold( body: Column(
appBar: const ChannelHeader(), children: const <Widget>[
body: Column( Expanded(
children: const <Widget>[ child: MessageListView(),
Expanded( ),
child: MessageListView(), MessageInput(),
), ],
MessageInput(), ),
], );
),
);
}
} }
@@ -92,26 +92,23 @@ class _ChannelListPageState extends State<ChannelListPage> {
); );
@override @override
// ignore: prefer_expression_function_bodies Widget build(BuildContext context) => Scaffold(
Widget build(BuildContext context) { body: RefreshIndicator(
return Scaffold( onRefresh: _controller.refresh,
body: RefreshIndicator( child: StreamChannelListView(
onRefresh: _controller.refresh, controller: _controller,
child: StreamChannelListView( onChannelTap: (channel) => Navigator.push(
controller: _controller, context,
onChannelTap: (channel) => Navigator.push( MaterialPageRoute(
context, builder: (_) => StreamChannel(
MaterialPageRoute( channel: channel,
builder: (_) => StreamChannel( child: const ChannelPage(),
channel: channel, ),
child: const ChannelPage(),
), ),
), ),
), ),
), ),
), );
);
}
} }
class ChannelPage extends StatelessWidget { class ChannelPage extends StatelessWidget {
@@ -120,18 +117,15 @@ class ChannelPage extends StatelessWidget {
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies Widget build(BuildContext context) => Scaffold(
Widget build(BuildContext context) { appBar: const ChannelHeader(),
return Scaffold( body: Column(
appBar: const ChannelHeader(), children: const <Widget>[
body: Column( Expanded(
children: const <Widget>[ child: MessageListView(),
Expanded( ),
child: MessageListView(), MessageInput(),
), ],
MessageInput(), ),
], );
),
);
}
} }
@@ -68,31 +68,49 @@ class MyApp extends StatelessWidget {
} }
} }
class ChannelListPage extends StatelessWidget { class ChannelListPage extends StatefulWidget {
const ChannelListPage({ const ChannelListPage({
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies State<ChannelListPage> createState() => _ChannelListPageState();
Widget build(BuildContext context) { }
return Scaffold(
body: ChannelsBloc(
child: ChannelListView(
filter: Filter.in_(
'members',
[StreamChat.of(context).currentUser!.id],
),
channelPreviewBuilder: _channelPreviewBuilder,
// sort: [SortOption('last_message_at')],
limit: 20,
channelWidget: const ChannelPage(),
),
),
);
}
Widget _channelPreviewBuilder(BuildContext context, Channel channel) { class _ChannelListPageState extends State<ChannelListPage> {
late final _listController = StreamChannelListController(
client: StreamChat.of(context).client,
filter: Filter.in_(
'members',
[StreamChat.of(context).currentUser!.id],
),
sort: const [SortOption('last_message_at')],
limit: 20,
);
@override
Widget build(BuildContext context) => Scaffold(
body: StreamChannelListView(
controller: _listController,
itemBuilder: _channelPreviewBuilder,
onChannelTap: (channel) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
),
);
},
),
);
Widget _channelPreviewBuilder(
BuildContext context,
Channel channel,
StreamChannelListTile defaultTile,
) {
final lastMessage = channel.state?.messages.reversed.firstWhereOrNull( final lastMessage = channel.state?.messages.reversed.firstWhereOrNull(
(message) => !message.isDeleted, (message) => !message.isDeleted,
); );
@@ -115,13 +133,14 @@ class ChannelListPage extends StatelessWidget {
leading: ChannelAvatar( leading: ChannelAvatar(
channel: channel, channel: channel,
), ),
title: ChannelName( title: StreamChannelName(
textStyle: ChannelPreviewTheme.of(context).titleStyle!.copyWith( textStyle: ChannelPreviewTheme.of(context).titleStyle!.copyWith(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
.textHighEmphasis .textHighEmphasis
.withOpacity(opacity), .withOpacity(opacity),
), ),
channel: channel,
), ),
subtitle: Text(subtitle), subtitle: Text(subtitle),
trailing: channel.state!.unreadCount > 0 trailing: channel.state!.unreadCount > 0
@@ -53,38 +53,42 @@ class MyApp extends StatelessWidget {
} }
} }
class ChannelListPage extends StatelessWidget { class ChannelListPage extends StatefulWidget {
const ChannelListPage({ const ChannelListPage({
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies State<ChannelListPage> createState() => _ChannelListPageState();
Widget build(BuildContext context) { }
return Scaffold(
body: StreamChannelListView( class _ChannelListPageState extends State<ChannelListPage> {
controller: StreamChannelListController( late final _listController = StreamChannelListController(
client: StreamChat.of(context).client, client: StreamChat.of(context).client,
filter: Filter.in_( filter: Filter.in_(
'members', 'members',
[StreamChat.of(context).currentUser!.id], [StreamChat.of(context).currentUser!.id],
), ),
sort: const [SortOption('last_message_at')], sort: const [SortOption('last_message_at')],
limit: 20, limit: 20,
), );
onChannelTap: (channel) {
Navigator.of(context).push( @override
MaterialPageRoute( Widget build(BuildContext context) => Scaffold(
builder: (context) => StreamChannel( body: StreamChannelListView(
channel: channel, controller: _listController,
child: const ChannelPage(), onChannelTap: (channel) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
), ),
), );
); },
}, ),
), );
);
}
} }
class ChannelPage extends StatelessWidget { class ChannelPage extends StatelessWidget {
@@ -59,28 +59,42 @@ class MyApp extends StatelessWidget {
} }
} }
class ChannelListPage extends StatelessWidget { class ChannelListPage extends StatefulWidget {
const ChannelListPage({ const ChannelListPage({
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies State<ChannelListPage> createState() => _ChannelListPageState();
Widget build(BuildContext context) { }
return Scaffold(
body: ChannelsBloc( class _ChannelListPageState extends State<ChannelListPage> {
child: ChannelListView( late final _listController = StreamChannelListController(
filter: Filter.in_( client: StreamChat.of(context).client,
'members', filter: Filter.in_(
[StreamChat.of(context).currentUser!.id], 'members',
), [StreamChat.of(context).currentUser!.id],
sort: const [SortOption('last_message_at')], ),
limit: 20, sort: const [SortOption('last_message_at')],
channelWidget: const ChannelPage(), limit: 20,
);
@override
Widget build(BuildContext context) => Scaffold(
body: StreamChannelListView(
controller: _listController,
onChannelTap: (channel) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
),
);
},
), ),
), );
);
}
} }
class ChannelPage extends StatelessWidget { class ChannelPage extends StatelessWidget {
@@ -93,28 +93,41 @@ class MyApp extends StatelessWidget {
} }
} }
class ChannelListPage extends StatelessWidget { class ChannelListPage extends StatefulWidget {
const ChannelListPage({ const ChannelListPage({
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies State<ChannelListPage> createState() => _ChannelListPageState();
Widget build(BuildContext context) { }
return Scaffold(
body: ChannelsBloc( class _ChannelListPageState extends State<ChannelListPage> {
child: ChannelListView( late final _listController = StreamChannelListController(
filter: Filter.in_( client: StreamChat.of(context).client,
'members', filter: Filter.in_(
[StreamChat.of(context).currentUser!.id], 'members',
), [StreamChat.of(context).currentUser!.id],
sort: const [SortOption('last_message_at')], ),
limit: 20, sort: const [SortOption('last_message_at')],
channelWidget: const ChannelPage(), limit: 20,
);
@override
Widget build(BuildContext context) => Scaffold(
body: StreamChannelListView(
controller: _listController,
onChannelTap: (channel) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
),
);
},
), ),
), );
);
}
} }
class ChannelPage extends StatelessWidget { class ChannelPage extends StatelessWidget {
@@ -123,24 +136,21 @@ class ChannelPage extends StatelessWidget {
}) : super(key: key); }) : super(key: key);
@override @override
// ignore: prefer_expression_function_bodies Widget build(BuildContext context) => Scaffold(
Widget build(BuildContext context) { appBar: const ChannelHeader(),
return Scaffold( body: Column(
appBar: const ChannelHeader(), children: <Widget>[
body: Column( Expanded(
children: <Widget>[ child: MessageListView(
Expanded( threadBuilder: (_, parentMessage) => ThreadPage(
child: MessageListView( parent: parentMessage,
threadBuilder: (_, parentMessage) => ThreadPage( ),
parent: parentMessage,
), ),
), ),
), const MessageInput(),
const MessageInput(), ],
], ),
), );
);
}
} }
class ThreadPage extends StatelessWidget { class ThreadPage extends StatelessWidget {
@@ -16,6 +16,7 @@ class GroupAvatar extends StatelessWidget {
this.selectionThickness = 4, this.selectionThickness = 4,
}) : super(key: key); }) : super(key: key);
/// The channel of the avatar
final Channel? channel; final Channel? channel;
/// List of images to display /// List of images to display
@@ -5,8 +5,10 @@ import 'package:stream_chat/stream_chat.dart' show StreamChatError;
part 'paged_value_notifier.freezed.dart'; part 'paged_value_notifier.freezed.dart';
/// Default initial page size multiplier.
const defaultInitialPagedLimitMultiplier = 3; const defaultInitialPagedLimitMultiplier = 3;
/// Value listenable for paged data.
typedef PagedValueListenableBuilder<Key, Value> typedef PagedValueListenableBuilder<Key, Value>
= ValueListenableBuilder<PagedValue<Key, Value>>; = ValueListenableBuilder<PagedValue<Key, Value>>;
@@ -57,6 +59,7 @@ abstract class PagedValueNotifier<Key, Value>
final nextPageKey = lastValue.nextPageKey; final nextPageKey = lastValue.nextPageKey;
// resetting the error // resetting the error
value = lastValue.copyWith(error: null); value = lastValue.copyWith(error: null);
// ignore: null_check_on_nullable_type_parameter
return loadMore(nextPageKey!); return loadMore(nextPageKey!);
} }
@@ -78,10 +81,9 @@ abstract class PagedValueNotifier<Key, Value>
Future<void> loadMore(Key nextPageKey); Future<void> loadMore(Key nextPageKey);
} }
/// Paged value that can be used with [PagedValueNotifier].
@freezed @freezed
abstract class PagedValue<Key, Value> with _$PagedValue<Key, Value> { abstract class PagedValue<Key, Value> with _$PagedValue<Key, Value> {
const PagedValue._();
/// Represents the success state of the [PagedValue] /// Represents the success state of the [PagedValue]
// @Assert( // @Assert(
// 'nextPageKey != null', // 'nextPageKey != null',
@@ -98,6 +100,8 @@ abstract class PagedValue<Key, Value> with _$PagedValue<Key, Value> {
StreamChatError? error, StreamChatError? error,
}) = Success<Key, Value>; }) = Success<Key, Value>;
const PagedValue._();
/// Represents the loading state of the [PagedValue]. /// Represents the loading state of the [PagedValue].
const factory PagedValue.loading() = Loading; const factory PagedValue.loading() = Loading;
@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:math';
import 'package:stream_chat/stream_chat.dart' hide Success; import 'package:stream_chat/stream_chat.dart' hide Success;
import 'package:stream_chat_flutter/src/paged_value_notifier.dart'; import 'package:stream_chat_flutter/src/paged_value_notifier.dart';
@@ -7,6 +8,8 @@ import 'package:stream_chat_flutter/src/v4/channel_list_view/stream_channel_list
/// The default channel page limit to load. /// The default channel page limit to load.
const defaultChannelPagedLimit = 10; const defaultChannelPagedLimit = 10;
const _kDefaultBackendPaginationLimit = 30;
/// A controller for a Channel list. /// A controller for a Channel list.
/// ///
/// This class lets you perform tasks such as: /// This class lets you perform tasks such as:
@@ -102,7 +105,10 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
@override @override
Future<void> doInitialLoad() async { Future<void> doInitialLoad() async {
final limit = this.limit * defaultInitialPagedLimitMultiplier; final limit = min(
this.limit * defaultInitialPagedLimitMultiplier,
_kDefaultBackendPaginationLimit,
);
try { try {
await for (final channels in client.queryChannels( await for (final channels in client.queryChannels(
filter: filter, filter: filter,
@@ -146,8 +146,8 @@ class StreamChannelListEventHandler {
/// Function which gets called for the event /// Function which gets called for the event
/// [EventType.notificationMessageNew]. /// [EventType.notificationMessageNew].
/// ///
/// This event is fired when a new message is created in a channel which we are /// This event is fired when a new message is created in a channel
/// not currently watching. /// which we are not currently watching.
/// ///
/// By default, this adds the channel and moves it to the top of list. /// By default, this adds the channel and moves it to the top of list.
void onNotificationMessageNew( void onNotificationMessageNew(
@@ -68,7 +68,8 @@ class StreamChannelListTile extends StatelessWidget {
/// {@template flutter.material.ListTile.tileColor} /// {@template flutter.material.ListTile.tileColor}
/// Defines the background color of `ListTile`. /// Defines the background color of `ListTile`.
/// ///
/// When the value is null, the `tileColor` is set to [ListTileTheme.tileColor] /// When the value is null,
/// the `tileColor` is set to [ListTileTheme.tileColor]
/// if it's not null and to [Colors.transparent] if it's null. /// if it's not null and to [Colors.transparent] if it's null.
/// {@endtemplate} /// {@endtemplate}
final Color? tileColor; final Color? tileColor;
@@ -143,9 +143,9 @@ class StreamChannelListView extends StatefulWidget {
/// only scroll the view if it has sufficient content. See [physics]. /// only scroll the view if it has sufficient content. See [physics].
/// ///
/// Also when true, the scroll view is used for default [ScrollAction]s. If a /// Also when true, the scroll view is used for default [ScrollAction]s. If a
/// ScrollAction is not handled by an otherwise focused part of the application, /// ScrollAction is not handled by an otherwise focused part of the
/// the ScrollAction will be evaluated using this scroll view, for example, /// application, the ScrollAction will be evaluated using this scroll view,
/// when executing [Shortcuts] key events like page up and down. /// for example, when executing [Shortcuts] key events like page up and down.
/// ///
/// On iOS, this also identifies the scroll view that will scroll to top in /// On iOS, this also identifies the scroll view that will scroll to top in
/// response to a tap in the status bar. /// response to a tap in the status bar.
@@ -229,8 +229,9 @@ const _kDefaultChannelInfoBottomSheetShape = RoundedRectangleBorder(
/// The [transitionAnimationController] controls the bottom sheet's entrance and /// The [transitionAnimationController] controls the bottom sheet's entrance and
/// exit animations if provided. /// exit animations if provided.
/// ///
/// The optional `routeSettings` parameter sets the [RouteSettings] of the modal bottom sheet /// The optional `routeSettings` parameter sets the [RouteSettings]
/// sheet. This is particularly useful in the case that a user wants to observe /// of the modal bottom sheet sheet.
/// This is particularly useful in the case that a user wants to observe
/// [PopupRoute]s within a [NavigatorObserver]. /// [PopupRoute]s within a [NavigatorObserver].
/// ///
/// Returns a `Future` that resolves to the value (if any) that was passed to /// Returns a `Future` that resolves to the value (if any) that was passed to
@@ -57,6 +57,10 @@ export 'src/utils.dart';
// v4 // v4
export 'src/v4/channel_list_view/stream_channel_list_controller.dart'; export 'src/v4/channel_list_view/stream_channel_list_controller.dart';
export 'src/v4/channel_list_view/stream_channel_list_event_handler.dart'; export 'src/v4/channel_list_view/stream_channel_list_event_handler.dart';
export 'src/v4/channel_list_view/stream_channel_list_loading_tile.dart';
export 'src/v4/channel_list_view/stream_channel_list_tile.dart';
export 'src/v4/channel_list_view/stream_channel_list_view.dart'; export 'src/v4/channel_list_view/stream_channel_list_view.dart';
export 'src/v4/stream_channel_avatar.dart';
export 'src/v4/stream_channel_info_bottom_sheet.dart'; export 'src/v4/stream_channel_info_bottom_sheet.dart';
export 'src/v4/stream_channel_name.dart';
export 'src/visible_footnote.dart'; export 'src/visible_footnote.dart';