Merge pull request #157 from GetStream/add-bottom-nav

Add bottomNavigationBar
This commit is contained in:
Salvatore Giordano
2020-11-30 09:44:29 +01:00
committed by GitHub
7 changed files with 171 additions and 102 deletions
+2 -4
View File
@@ -155,11 +155,9 @@ class ChooseUserPage extends StatelessWidget {
if (!kIsWeb) { if (!kIsWeb) {
initNotifications(client); initNotifications(client);
} }
Navigator.pushNamedAndRemoveUntil( Navigator.pushReplacementNamed(
context, context,
Routes.CHANNEL_LIST, Routes.HOME,
ModalRoute.withName(Routes.CHANNEL_LIST),
arguments: client,
); );
}, },
leading: UserAvatar( leading: UserAvatar(
+1 -1
View File
@@ -132,7 +132,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
Navigator.pushNamedAndRemoveUntil( Navigator.pushNamedAndRemoveUntil(
context, context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
ModalRoute.withName(Routes.CHANNEL_LIST), ModalRoute.withName(Routes.HOME),
arguments: channel, arguments: channel,
); );
}, },
+162 -92
View File
@@ -60,51 +60,53 @@ class MyApp extends StatelessWidget {
//TODO change to system once dark theme is implemented //TODO change to system once dark theme is implemented
themeMode: ThemeMode.light, themeMode: ThemeMode.light,
onGenerateRoute: AppRoutes.generateRoute, onGenerateRoute: AppRoutes.generateRoute,
initialRoute: client.state.user == null initialRoute:
? Routes.CHOOSE_USER client.state.user == null ? Routes.CHOOSE_USER : Routes.HOME,
: Routes.CHANNEL_LIST,
), ),
); );
} }
} }
class ChannelListPage extends StatefulWidget { class HomePage extends StatefulWidget {
@override @override
_ChannelListPageState createState() => _ChannelListPageState(); _HomePageState createState() => _HomePageState();
} }
class _ChannelListPageState extends State<ChannelListPage> { class _HomePageState extends State<HomePage> {
TextEditingController _controller; int _currentIndex = 0;
String _channelQuery = ''; bool _isSelected(int index) => _currentIndex == index;
bool _isSearchActive = false; List<BottomNavigationBarItem> get _navBarItems {
return <BottomNavigationBarItem>[
Timer _debounce; BottomNavigationBarItem(
icon: Stack(
void _channelQueryListener() { overflow: Overflow.visible,
if (_debounce?.isActive ?? false) _debounce.cancel(); children: [
_debounce = Timer(const Duration(milliseconds: 350), () { StreamSvgIcon.message(
if (mounted) { color: _isSelected(0) ? Colors.black : Colors.grey,
setState(() { ),
_channelQuery = _controller.text; Positioned(
_isSearchActive = _channelQuery.isNotEmpty; top: -3,
}); right: -16,
} child: UnreadIndicator(),
}); ),
} ],
),
@override label: 'Chats',
void initState() { ),
super.initState(); BottomNavigationBarItem(
_controller = TextEditingController()..addListener(_channelQueryListener); icon: Stack(
} overflow: Overflow.visible,
children: [
@override StreamSvgIcon.mentions(
void dispose() { color: _isSelected(1) ? Colors.black : Colors.grey,
_controller?.removeListener(_channelQueryListener); ),
_controller?.dispose(); ],
super.dispose(); ),
label: 'Mentions',
),
];
} }
@override @override
@@ -118,63 +120,22 @@ class _ChannelListPageState extends State<ChannelListPage> {
), ),
drawer: _buildDrawer(context, user), drawer: _buildDrawer(context, user),
drawerEdgeDragWidth: 50, drawerEdgeDragWidth: 50,
body: ChannelsBloc( bottomNavigationBar: BottomNavigationBar(
child: MessageSearchBloc( currentIndex: _currentIndex,
child: Column( items: _navBarItems,
children: [ type: BottomNavigationBarType.fixed,
SearchTextField( selectedItemColor: Colors.black,
controller: _controller, unselectedItemColor: Colors.grey,
), onTap: (index) {
Expanded( setState(() => _currentIndex = index);
child: AnimatedSwitcher( },
duration: const Duration(milliseconds: 350), ),
child: GestureDetector( body: IndexedStack(
behavior: HitTestBehavior.opaque, index: _currentIndex,
onPanDown: (_) => FocusScope.of(context).unfocus(), children: [
child: _isSearchActive ChannelListPage(),
? MessageSearchListView( UserMentionPage(),
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(),
),
),
),
),
],
),
),
), ),
); );
} }
@@ -282,6 +243,115 @@ class _ChannelListPageState extends State<ChannelListPage> {
} }
} }
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<ChannelListPage> {
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 { class ChannelQuerySearchResultPage extends StatelessWidget {
final Stream<List<Message>> searchResultStream; final Stream<List<Message>> searchResultStream;
+1 -1
View File
@@ -338,7 +338,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
Navigator.pushNamedAndRemoveUntil( Navigator.pushNamedAndRemoveUntil(
context, context,
Routes.CHANNEL_PAGE, Routes.CHANNEL_PAGE,
ModalRoute.withName(Routes.CHANNEL_LIST), ModalRoute.withName(Routes.HOME),
arguments: channel, arguments: channel,
); );
} }
+3 -3
View File
@@ -13,11 +13,11 @@ class AppRoutes {
static Route<dynamic> generateRoute(RouteSettings settings) { static Route<dynamic> generateRoute(RouteSettings settings) {
final args = settings.arguments; final args = settings.arguments;
switch (settings.name) { switch (settings.name) {
case Routes.CHANNEL_LIST: case Routes.HOME:
return MaterialPageRoute( return MaterialPageRoute(
settings: const RouteSettings(name: Routes.CHANNEL_LIST), settings: const RouteSettings(name: Routes.HOME),
builder: (_) { builder: (_) {
return ChannelListPage(); return HomePage();
}); });
case Routes.CHOOSE_USER: case Routes.CHOOSE_USER:
return MaterialPageRoute( return MaterialPageRoute(
+1 -1
View File
@@ -1,6 +1,6 @@
/// Define all the route names here /// Define all the route names here
class Routes { class Routes {
static const String CHANNEL_LIST = '/channel_list'; static const String HOME = '/home';
static const String CHOOSE_USER = '/choose_user'; static const String CHOOSE_USER = '/choose_user';
static const String ADVANCED_OPTIONS = '/advance_options'; static const String ADVANCED_OPTIONS = '/advance_options';
static const String CHANNEL_PAGE = '/channel_page'; static const String CHANNEL_PAGE = '/channel_page';
+1
View File
@@ -41,3 +41,4 @@ export 'src/video_attachment.dart';
export 'src/message_search_bloc.dart'; export 'src/message_search_bloc.dart';
export 'src/message_search_item.dart'; export 'src/message_search_item.dart';
export 'src/message_search_list_view.dart'; export 'src/message_search_list_view.dart';
export 'src/unread_indicator.dart';