Files
flutter-samples/packages/stream_chat_v1/lib/channel_list.dart
T
2021-08-24 11:39:49 +02:00

202 lines
7.4 KiB
Dart

import 'dart:async';
import 'package:example/localizations.dart';
import 'package:example/routes/routes.dart';
import 'package:example/search_text_field.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'channel_page.dart';
import 'chat_info_screen.dart';
import 'group_info_screen.dart';
class ChannelList extends StatefulWidget {
@override
_ChannelList createState() => _ChannelList();
}
class _ChannelList extends State<ChannelList> {
TextEditingController? _controller;
String _channelQuery = '';
bool _isSearchActive = false;
Timer? _debounce;
void _channelQueryListener() {
if (_debounce?.isActive ?? false) _debounce!.cancel();
_debounce = Timer(const Duration(milliseconds: 350), () {
if (mounted) {
setState(() {
_channelQuery = _controller!.text;
_isSearchActive = _channelQuery.isNotEmpty;
});
}
});
}
@override
void initState() {
super.initState();
_controller = TextEditingController()..addListener(_channelQueryListener);
}
@override
void dispose() {
_controller?.removeListener(_channelQueryListener);
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final user = StreamChat.of(context).currentUser;
return WillPopScope(
onWillPop: () async {
if (_isSearchActive) {
_controller!.clear();
setState(() => _isSearchActive = false);
return false;
}
return true;
},
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (_, __) => [
SliverToBoxAdapter(
child: SearchTextField(
controller: _controller,
showCloseButton: _isSearchActive,
hintText: AppLocalizations.of(context).search,
),
),
],
body: AnimatedSwitcher(
duration: const Duration(milliseconds: 350),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onPanDown: (_) => FocusScope.of(context).unfocus(),
child: _isSearchActive
? MessageSearchBloc(
child: MessageSearchListView(
showErrorTile: true,
messageQuery: _channelQuery,
filters: Filter.in_('members', [user!.id]),
sortOptions: [
SortOption(
'created_at',
direction: SortOption.ASC,
),
],
pullToRefresh: false,
paginationParams: PaginationParams(limit: 20),
emptyBuilder: (_) {
return LayoutBuilder(
builder: (context, viewportConstraints) {
return SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(24),
child: StreamSvgIcon.search(
size: 96,
color: Colors.grey,
),
),
Text(
AppLocalizations.of(context).noResults,
),
],
),
),
),
);
},
);
},
onItemTap: (messageResponse) async {
FocusScope.of(context).requestFocus(FocusNode());
final client = StreamChat.of(context).client;
final message = messageResponse.message;
final channel = client.channel(
messageResponse.channel!.type,
id: messageResponse.channel!.id,
);
if (channel.state == null) {
await channel.watch();
}
Navigator.pushNamed(
context,
Routes.CHANNEL_PAGE,
arguments: ChannelPageArgs(
channel: channel,
initialMessage: message,
),
);
},
),
)
: ChannelsBloc(
child: ChannelListView(
onStartChatPressed: () {
Navigator.pushNamed(context, Routes.NEW_CHAT);
},
swipeToAction: true,
filter: Filter.in_('members', [user!.id]),
presence: true,
pagination: PaginationParams(
limit: 20,
),
channelWidget: ChannelPage(),
onViewInfoTap: (channel) {
Navigator.pop(context);
if (channel.memberCount == 2 && channel.isDistinct) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: ChatInfoScreen(
messageTheme: StreamChatTheme.of(context)
.ownMessageTheme,
user: channel.state!.members
.where((m) =>
m.userId !=
channel.client.state.currentUser!.id)
.first
.user,
),
),
),
);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: GroupInfoScreen(
messageTheme: StreamChatTheme.of(context)
.ownMessageTheme,
),
),
),
);
}
},
),
),
),
),
),
);
}
}