Skip to content

Instantly share code, notes, and snippets.

@HayesGordon
Last active February 18, 2022 17:26
Show Gist options
  • Save HayesGordon/75faaf6f7cab48ff06a803b3b7d7124c to your computer and use it in GitHub Desktop.
Save HayesGordon/75faaf6f7cab48ff06a803b3b7d7124c to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/scrollable_positioned_list/scrollable_positioned_list.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
Future<void> main() async {
final client = StreamChatClient(
'YOUR-KEY',
logLevel: Level.INFO,
);
await client.connectUser(YOUR-USER);
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: const ChannelListPage(),
);
}
}
class ChannelListPage extends StatelessWidget {
const ChannelListPage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ChannelsBloc(
child: ChannelListView(
filter: Filter.in_(
'members',
[StreamChat.of(context).currentUser!.id],
),
sort: const [SortOption('last_message_at')],
limit: 20,
channelWidget: const ChannelPage(),
),
),
);
}
}
class ChannelPage extends StatelessWidget {
const ChannelPage({
Key? key,
this.jumpToLastUnread = 0,
}) : super(key: key);
final int jumpToLastUnread;
@override
Widget build(BuildContext context) {
final channel = StreamChannel.of(context).channel;
return Scaffold(
appBar: const ChannelHeader(),
body: Column(
children: <Widget>[
Expanded(
child: MyMessageList(
channel: channel,
),
),
const MessageInput(),
],
),
);
}
}
class MyMessageList extends StatefulWidget {
const MyMessageList({
Key? key,
required this.channel,
}) : super(key: key);
final Channel channel;
@override
State<MyMessageList> createState() => _MyMessageListState();
}
class _MyMessageListState extends State<MyMessageList> {
final controller = ItemScrollController();
@override
Widget build(BuildContext context) => Stack(
children: [
MessageListView(
showScrollToBottom: false,
scrollController: controller,
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(16),
child: ScrollToUnreadButton(
channel: widget.channel,
scrollController: controller,
),
),
)
],
);
}
class ScrollToUnreadButton extends StatelessWidget {
const ScrollToUnreadButton({
Key? key,
required this.channel,
required this.scrollController,
}) : super(key: key);
final Channel channel;
final ItemScrollController scrollController;
Future<void> _scrollTo(
BuildContext context, {
required int index,
required double alignment,
}) async {
if (!channel.state!.isUpToDate) {
await StreamChannel.of(context).loadChannelAtMessage(
null,
before: index + 25,
);
WidgetsBinding.instance?.addPostFrameCallback((_) {
scrollController.jumpTo(index: index);
});
} else {
scrollController.scrollTo(
index: index,
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
);
}
}
@override
Widget build(BuildContext context) => BetterStreamBuilder<int>(
stream: channel.state?.unreadCountStream,
initialData: channel.state?.unreadCount,
builder: (context, count) {
if (count == 0 || count == 0) {
return const SizedBox.shrink();
}
return FloatingActionButton(
onPressed: () {
_scrollTo(context, index: count, alignment: 0);
},
child: const Icon(Icons.arrow_downward),
);
},
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment