From c137ffcc6dfd18d6422108b6bbbef8c6a6b90794 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 27 Nov 2020 19:03:48 +0530 Subject: [PATCH] Add bottomNavigationBar Signed-off-by: Sahil Kumar --- example/lib/choose_user_page.dart | 6 +- example/lib/group_chat_details_screen.dart | 2 +- example/lib/main.dart | 254 +++++++++++++-------- example/lib/new_chat_screen.dart | 2 +- example/lib/routes/app_routes.dart | 6 +- example/lib/routes/routes.dart | 2 +- lib/stream_chat_flutter.dart | 1 + 7 files changed, 171 insertions(+), 102 deletions(-) diff --git a/example/lib/choose_user_page.dart b/example/lib/choose_user_page.dart index 844a8c77..80b76f92 100644 --- a/example/lib/choose_user_page.dart +++ b/example/lib/choose_user_page.dart @@ -155,11 +155,9 @@ class ChooseUserPage extends StatelessWidget { if (!kIsWeb) { initNotifications(client); } - Navigator.pushNamedAndRemoveUntil( + Navigator.pushReplacementNamed( context, - Routes.CHANNEL_LIST, - ModalRoute.withName(Routes.CHANNEL_LIST), - arguments: client, + Routes.HOME, ); }, leading: UserAvatar( diff --git a/example/lib/group_chat_details_screen.dart b/example/lib/group_chat_details_screen.dart index 88de33a9..d759a82e 100644 --- a/example/lib/group_chat_details_screen.dart +++ b/example/lib/group_chat_details_screen.dart @@ -132,7 +132,7 @@ class _GroupChatDetailsScreenState extends State { Navigator.pushNamedAndRemoveUntil( context, Routes.CHANNEL_PAGE, - ModalRoute.withName(Routes.CHANNEL_LIST), + ModalRoute.withName(Routes.HOME), arguments: channel, ); }, diff --git a/example/lib/main.dart b/example/lib/main.dart index 26590237..fa62878d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -60,51 +60,53 @@ class MyApp extends StatelessWidget { //TODO change to system once dark theme is implemented themeMode: ThemeMode.light, onGenerateRoute: AppRoutes.generateRoute, - initialRoute: client.state.user == null - ? Routes.CHOOSE_USER - : Routes.CHANNEL_LIST, + initialRoute: + client.state.user == null ? Routes.CHOOSE_USER : Routes.HOME, ), ); } } -class ChannelListPage extends StatefulWidget { +class HomePage extends StatefulWidget { @override - _ChannelListPageState createState() => _ChannelListPageState(); + _HomePageState createState() => _HomePageState(); } -class _ChannelListPageState extends State { - TextEditingController _controller; +class _HomePageState extends State { + int _currentIndex = 0; - String _channelQuery = ''; + bool _isSelected(int index) => _currentIndex == index; - 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(); + List get _navBarItems { + return [ + BottomNavigationBarItem( + icon: Stack( + overflow: Overflow.visible, + children: [ + StreamSvgIcon.message( + color: _isSelected(0) ? Colors.black : Colors.grey, + ), + Positioned( + top: -3, + right: -16, + child: UnreadIndicator(), + ), + ], + ), + label: 'Chats', + ), + BottomNavigationBarItem( + icon: Stack( + overflow: Overflow.visible, + children: [ + StreamSvgIcon.mentions( + color: _isSelected(1) ? Colors.black : Colors.grey, + ), + ], + ), + label: 'Mentions', + ), + ]; } @override @@ -118,63 +120,22 @@ class _ChannelListPageState extends State { ), drawer: _buildDrawer(context, user), drawerEdgeDragWidth: 50, - body: ChannelsBloc( - child: MessageSearchBloc( - child: Column( - children: [ - SearchTextField( - controller: _controller, - ), - Expanded( - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 350), - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: _isSearchActive - ? MessageSearchListView( - messageQuery: _channelQuery, - filters: { - 'members': { - r'$in': [user.id] - } - }, - sortOptions: [ - SortOption( - 'created_at', - direction: SortOption.ASC, - ), - ], - paginationParams: PaginationParams(limit: 20), - onItemTap: (message) {}, - ) - : ChannelListView( - onStartChatPressed: () { - Navigator.pushNamed(context, Routes.NEW_CHAT); - }, - swipeToAction: true, - filter: { - 'members': { - r'$in': [user.id], - }, - 'draft': { - r'$ne': true, - }, - }, - options: { - 'presence': true, - }, - pagination: PaginationParams( - limit: 20, - ), - channelWidget: ChannelPage(), - ), - ), - ), - ), - ], - ), - ), + bottomNavigationBar: BottomNavigationBar( + currentIndex: _currentIndex, + items: _navBarItems, + type: BottomNavigationBarType.fixed, + selectedItemColor: Colors.black, + unselectedItemColor: Colors.grey, + onTap: (index) { + setState(() => _currentIndex = index); + }, + ), + body: IndexedStack( + index: _currentIndex, + children: [ + ChannelListPage(), + UserMentionPage(), + ], ), ); } @@ -282,6 +243,115 @@ class _ChannelListPageState extends State { } } +class UserMentionPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Text('On Pause Right Now!'), + ); + } +} + +class ChannelListPage extends StatefulWidget { + @override + _ChannelListPageState createState() => _ChannelListPageState(); +} + +class _ChannelListPageState extends State { + 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).user; + return ChannelsBloc( + child: MessageSearchBloc( + child: Column( + children: [ + SearchTextField( + controller: _controller, + ), + Expanded( + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 350), + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: _isSearchActive + ? MessageSearchListView( + messageQuery: _channelQuery, + filters: { + 'members': { + r'$in': [user.id] + } + }, + sortOptions: [ + SortOption( + 'created_at', + direction: SortOption.ASC, + ), + ], + paginationParams: PaginationParams(limit: 20), + onItemTap: (message) {}, + ) + : ChannelListView( + onStartChatPressed: () { + Navigator.pushNamed(context, Routes.NEW_CHAT); + }, + swipeToAction: true, + filter: { + 'members': { + r'$in': [user.id], + }, + }, + options: { + 'presence': true, + }, + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + ), + ), + ), + ), + ], + ), + ), + ); + } +} + class ChannelQuerySearchResultPage extends StatelessWidget { final Stream> searchResultStream; diff --git a/example/lib/new_chat_screen.dart b/example/lib/new_chat_screen.dart index 364c8b7e..5fbfbf07 100644 --- a/example/lib/new_chat_screen.dart +++ b/example/lib/new_chat_screen.dart @@ -338,7 +338,7 @@ class _NewChatScreenState extends State { Navigator.pushNamedAndRemoveUntil( context, Routes.CHANNEL_PAGE, - ModalRoute.withName(Routes.CHANNEL_LIST), + ModalRoute.withName(Routes.HOME), arguments: channel, ); } diff --git a/example/lib/routes/app_routes.dart b/example/lib/routes/app_routes.dart index 19352319..6b0529e1 100644 --- a/example/lib/routes/app_routes.dart +++ b/example/lib/routes/app_routes.dart @@ -13,11 +13,11 @@ class AppRoutes { static Route generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { - case Routes.CHANNEL_LIST: + case Routes.HOME: return MaterialPageRoute( - settings: const RouteSettings(name: Routes.CHANNEL_LIST), + settings: const RouteSettings(name: Routes.HOME), builder: (_) { - return ChannelListPage(); + return HomePage(); }); case Routes.CHOOSE_USER: return MaterialPageRoute( diff --git a/example/lib/routes/routes.dart b/example/lib/routes/routes.dart index f4ace9a4..0e0b1e57 100644 --- a/example/lib/routes/routes.dart +++ b/example/lib/routes/routes.dart @@ -1,6 +1,6 @@ /// Define all the route names here class Routes { - static const String CHANNEL_LIST = '/channel_list'; + static const String HOME = '/home'; static const String CHOOSE_USER = '/choose_user'; static const String ADVANCED_OPTIONS = '/advance_options'; static const String CHANNEL_PAGE = '/channel_page'; diff --git a/lib/stream_chat_flutter.dart b/lib/stream_chat_flutter.dart index 35239cbd..1cbe21e4 100644 --- a/lib/stream_chat_flutter.dart +++ b/lib/stream_chat_flutter.dart @@ -41,3 +41,4 @@ export 'src/video_attachment.dart'; export 'src/message_search_bloc.dart'; export 'src/message_search_item.dart'; export 'src/message_search_list_view.dart'; +export 'src/unread_indicator.dart';