dependencies:
flutter:
sdk: flutter
stream_chat_flutter: ^6.0.0
flutter_slidable: ^3.0.0
Channel List Preview
Slidable Channel List Preview
Introduction
The default slidable behavior within the channel list has been removed in v4 of the Stream Chat Flutter SDK. This guide will show you how you can easily add this functionality yourself.
Please see our full v4 migration guide if you’re migrating from an earlier version of the Stream Chat Flutter SDK.
Prerequisites
This guide assumes you are familiar with the Stream Chat SDK. If you’re new to Stream Chat Flutter, we recommend looking at our getting started tutorial.
Dependencies:
⚠️ Note: The examples shown in this guide use the above packages and versions.
Example Code - Custom Stream Channel Item Builder
In this example, you are doing a few important things in the ChannelListPage widget. You’re:
- Using the flutter_slidable package to easily add slide functionality.
- Passing in the
itemBuilder
argument for the StreamChannelListView widget. This gives access to the current BuildContext, Channel, and StreamChannelListTile, and allows you to create, or customize, the stream channel list tiles. - Returning a Slidable widget with two CustomSlidableAction widgets - to delete a channel and show more options. These widgets come from the flutter_slidable package.
- Adding
onPressed
behaviour to callshowConfirmationBottomSheet
andshowChannelInfoModalBottomSheet
. These methods come from thestream_chat_flutter
package. They have a few different on-tap callbacks you can supply, for example,onViewInfoTap
. Alternatively, you can create custom dialog screens from scratch. - Using the StreamChannelListController to perform actions, such as,
deleteChannel
.
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
void main() async {
final client = StreamChatClient(
's2dxdhpxd94g',
);
await client.connectUser(
User(id: 'super-band-9'),
'''eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A''',
);
runApp(
MyApp(
client: client,
),
);
}
class MyApp extends StatelessWidget {
const MyApp({
Key? key,
required this.client,
}) : super(key: key);
final StreamChatClient client;
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, child) => StreamChat(
client: client,
child: child,
),
home: ChannelListPage(
client: client,
),
);
}
}
class ChannelListPage extends StatefulWidget {
const ChannelListPage({
Key? key,
required this.client,
}) : super(key: key);
final StreamChatClient client;
@override
State<ChannelListPage> createState() => _ChannelListPageState();
}
class _ChannelListPageState extends State<ChannelListPage> {
late final _controller = StreamChannelListController(
client: widget.client,
filter: Filter.in_(
'members',
[StreamChat.of(context).currentUser!.id],
),
channelStateSort: const [SortOption('last_message_at')],
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scaffold(
body: SlidableAutoCloseBehavior(
child: RefreshIndicator(
onRefresh: _controller.refresh,
child: StreamChannelListView(
controller: _controller,
itemBuilder: (context, channels, index, tile) {
final channel = channels[index];
final chatTheme = StreamChatTheme.of(context);
final backgroundColor = chatTheme.colorTheme.inputBg;
final canDeleteChannel = channel.ownCapabilities
.contains(PermissionType.deleteChannel);
return Slidable(
groupTag: 'channels-actions',
endActionPane: ActionPane(
extentRatio: canDeleteChannel ? 0.40 : 0.20,
motion: const BehindMotion(),
children: [
CustomSlidableAction(
onPressed: (_) {
showChannelInfoModalBottomSheet(
context: context,
channel: channel,
onViewInfoTap: () {
Navigator.pop(context);
// Navigate to info screen
},
);
},
backgroundColor: backgroundColor,
child: const Icon(Icons.more_horiz),
),
if (canDeleteChannel)
CustomSlidableAction(
backgroundColor: backgroundColor,
child: StreamSvgIcon.delete(
color: chatTheme.colorTheme.accentError,
),
onPressed: (_) async {
final res = await showConfirmationBottomSheet(
context,
title: 'Delete Conversation',
question:
'Are you sure you want to delete this conversation?',
okText: 'Delete',
cancelText: 'Cancel',
icon: StreamSvgIcon.delete(
color: chatTheme.colorTheme.accentError,
),
);
if (res == true) {
await _controller.deleteChannel(channel);
}
},
),
],
),
child: tile,
);
},
onChannelTap: (channel) => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
),
),
),
),
),
);
}
class ChannelPage extends StatelessWidget {
const ChannelPage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) => Scaffold(
appBar: const StreamChannelHeader(),
body: Column(
children: const <Widget>[
Expanded(
child: StreamMessageListView(),
),
StreamMessageInput(),
],
),
);
}
The above is the complete sample, and all you need for a basic implementation.