add customize_channel_preview example

This commit is contained in:
Salvatore Giordano
2020-02-25 12:09:17 +01:00
parent 81f0381a96
commit 65d9d7889d
7 changed files with 156 additions and 91 deletions
@@ -5,6 +5,7 @@
In most cases you can leave this as-is, but you if you want to provide In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. --> FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"
android:label="example" android:label="example"
@@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
void main() async {
final client = Client('qk4nn7rpcn75');
await client.setUser(
User(id: 'wild-breeze-7'),
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo',
);
runApp(
StreamChat(
client: client,
child: MaterialApp(
home: ChannelListPage(),
),
),
);
}
class ChannelListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ChannelListView(
filter: {
'members': {
'\$in': [StreamChat.of(context).user.id],
}
},
channelPreviewBuilder: (context, channelClient) {
final channelState = channelClient.state.channelState;
return ListTile(
leading: CircleAvatar(
backgroundImage:
channelState.channel.extraData.containsKey('image')
? NetworkImage(channelState.channel.extraData['image'])
: null,
),
title: Text(channelState.channel.extraData['name'] ?? ''),
trailing: channelClient.state.unreadCount > 0
? CircleAvatar(
radius: 10,
child: Text(channelClient.state.unreadCount.toString()),
)
: Container(),
);
},
sort: [SortOption('last_message_at')],
pagination: PaginationParams(
limit: 20,
),
channelWidget: ChannelPage(),
),
);
}
}
class ChannelPage extends StatelessWidget {
const ChannelPage({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: MessageListView(),
),
MessageInput(),
],
),
);
}
}
+2 -2
View File
@@ -5,7 +5,7 @@ void main() async {
final client = Client('qk4nn7rpcn75'); final client = Client('qk4nn7rpcn75');
await client.setUser( await client.setUser(
User(id: "wild-breeze-7"), User(id: 'wild-breeze-7'),
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo',
); );
@@ -29,7 +29,7 @@ class ChannelListPage extends StatelessWidget {
'\$in': [StreamChat.of(context).user.id], '\$in': [StreamChat.of(context).user.id],
} }
}, },
sort: [SortOption("last_message_at")], sort: [SortOption('last_message_at')],
pagination: PaginationParams( pagination: PaginationParams(
limit: 20, limit: 20,
), ),
+2 -1
View File
@@ -5,12 +5,13 @@ void main() async {
final client = Client('qk4nn7rpcn75'); final client = Client('qk4nn7rpcn75');
await client.setUser( await client.setUser(
User(id: "wild-breeze-7"), User(id: 'wild-breeze-7'),
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo',
); );
final channelClient = client.channel('messaging', id: 'godevs'); final channelClient = client.channel('messaging', id: 'godevs');
// ignore: unawaited_futures
channelClient.watch(); channelClient.watch();
runApp( runApp(
+41 -28
View File
@@ -6,6 +6,7 @@ import 'stream_channel.dart';
import 'stream_chat.dart'; import 'stream_chat.dart';
typedef ChannelTapCallback = void Function(ChannelClient, Widget); typedef ChannelTapCallback = void Function(ChannelClient, Widget);
typedef ChannelPreviewBuilder = Widget Function(BuildContext, ChannelClient);
class ChannelListView extends StatefulWidget { class ChannelListView extends StatefulWidget {
ChannelListView({ ChannelListView({
@@ -16,7 +17,7 @@ class ChannelListView extends StatefulWidget {
this.pagination, this.pagination,
this.onChannelTap, this.onChannelTap,
this.channelWidget, this.channelWidget,
this.channelPreview, this.channelPreviewBuilder,
}) : assert(channelWidget != null || onChannelTap != null), }) : assert(channelWidget != null || onChannelTap != null),
super(key: key); super(key: key);
@@ -27,7 +28,7 @@ class ChannelListView extends StatefulWidget {
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
final ChannelTapCallback onChannelTap; final ChannelTapCallback onChannelTap;
final Widget channelWidget; final Widget channelWidget;
final Widget channelPreview; final ChannelPreviewBuilder channelPreviewBuilder;
@override @override
_ChannelListViewState createState() => _ChannelListViewState(); _ChannelListViewState createState() => _ChannelListViewState();
@@ -117,34 +118,46 @@ class _ChannelListViewState extends State<ChannelListView> {
}; };
} }
Widget child;
if (widget.channelPreview != null) {
child = Stack(
children: [
widget.channelPreview,
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
onTap(channelClient, widget.channelWidget);
},
),
),
),
],
);
} else {
child = ChannelPreview(
onTap: (channelClient) {
onTap(channelClient, widget.channelWidget);
},
);
}
return StreamChannel( return StreamChannel(
key: ValueKey<String>('CHANNEL-${channelClient.id}'), key: ValueKey<String>('CHANNEL-${channelClient.id}'),
child: child, child: StreamBuilder<ChannelState>(
initialData: channelClient.state.channelState,
stream: channelClient.state.channelStateStream,
builder: (context, snapshot) {
final channelState = snapshot.data;
Widget child;
if (widget.channelPreviewBuilder != null) {
child = Stack(
children: [
widget.channelPreviewBuilder(
context,
channelClient,
),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
onTap(channelClient, widget.channelWidget);
},
),
),
),
],
);
} else {
child = ChannelPreview(
channelClient: channelClient,
onTap: (channelClient) {
onTap(channelClient, widget.channelWidget);
},
);
}
return child;
},
),
channelClient: channelClient, channelClient: channelClient,
); );
} else { } else {
+30 -59
View File
@@ -5,62 +5,38 @@ import 'package:stream_chat/stream_chat.dart';
import 'channel_image.dart'; import 'channel_image.dart';
import 'channel_name_text.dart'; import 'channel_name_text.dart';
import 'stream_channel.dart';
import 'stream_chat.dart';
class ChannelPreview extends StatelessWidget { class ChannelPreview extends StatelessWidget {
final void Function(ChannelClient) onTap; final void Function(ChannelClient) onTap;
final ChannelState channelState;
final ChannelClient channelClient;
const ChannelPreview({ ChannelPreview({
@required this.channelClient,
Key key, Key key,
this.onTap, this.onTap,
}) : super(key: key); }) : channelState = channelClient.state.channelState,
super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final streamChannel = StreamChannel.of(context); return ListTile(
return StreamBuilder<ChannelState>( onTap: () {
stream: streamChannel.channelClient.state.channelStateStream, onTap(channelClient);
initialData: streamChannel.channelState, },
builder: (context, snapshot) { leading: ChannelImage(
final channelState = snapshot.data; channel: channelState.channel,
return _buildChannelPreview( ),
context, title: ChannelNameText(
channelState, channel: channelState.channel,
streamChannel, ),
); subtitle: _buildSubtitle(),
}); trailing: Column(
} mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
StreamChannel _buildChannelPreview( children: <Widget>[
BuildContext context, _buildDate(context, channelState.channel.lastMessageAt),
ChannelState channelState, ],
StreamChannelState streamChannel,
) {
final channelClient =
StreamChat.of(context).client.channelClients[channelState.channel.id];
return StreamChannel(
channelClient: channelClient,
child: ListTile(
onTap: () {
onTap(channelClient);
},
leading: ChannelImage(
channel: channelState.channel,
),
title: ChannelNameText(
channel: channelState.channel,
),
subtitle: _buildSubtitle(
streamChannel,
),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
_buildDate(context, channelState.channel.lastMessageAt),
],
),
), ),
); );
} }
@@ -86,27 +62,22 @@ class ChannelPreview extends StatelessWidget {
); );
} }
Widget _buildSubtitle( Widget _buildSubtitle() {
StreamChannelState streamChannel,
) {
return StreamBuilder<List<User>>( return StreamBuilder<List<User>>(
stream: streamChannel.channelClient.state.typingEventsStream, stream: channelClient.state.typingEventsStream,
initialData: [], initialData: [],
builder: (context, snapshot) { builder: (context, snapshot) {
final typings = snapshot.data; final typings = snapshot.data;
final opacity = final opacity = channelClient.state.unreadCount > .0 ? 1.0 : 0.5;
streamChannel.channelClient.state.unreadCount > .0 ? 1.0 : 0.5;
return typings.isNotEmpty return typings.isNotEmpty
? _buildTypings(typings, context, opacity) ? _buildTypings(typings, context, opacity)
: _buildLastMessage(context, streamChannel, opacity); : _buildLastMessage(context, opacity);
}); });
} }
Widget _buildLastMessage( Widget _buildLastMessage(BuildContext context, double opacity) {
BuildContext context, StreamChannelState streamChannel, double opacity) { final lastMessage =
final lastMessage = streamChannel.channelState.messages.isNotEmpty channelState.messages.isNotEmpty ? channelState.messages.last : null;
? streamChannel.channelState.messages.last
: null;
if (lastMessage == null) { if (lastMessage == null) {
return SizedBox.fromSize( return SizedBox.fromSize(
size: Size.zero, size: Size.zero,
+2 -1
View File
@@ -19,7 +19,8 @@ dependencies:
video_player: ^0.10.7 video_player: ^0.10.7
chewie: ^0.9.8+1 chewie: ^0.9.8+1
animations: ^1.0.0+3 animations: ^1.0.0+3
stream_chat: ^0.1.6 stream_chat:
path: ../stream_chat_dart
dev_dependencies: dev_dependencies:
pedantic: ^1.8.0+1 pedantic: ^1.8.0+1