import 'package:comunic/helpers/account_helper.dart'; import 'package:comunic/ui/routes/account_settings/account_settings_route.dart'; import 'package:comunic/ui/routes/app_settings_route.dart'; import 'package:comunic/ui/routes/conversation_route.dart'; import 'package:comunic/ui/routes/login_route.dart'; import 'package:comunic/ui/routes/main_route/page_info.dart'; import 'package:comunic/ui/screens/call_screen.dart'; import 'package:comunic/ui/screens/conversations_list_screen.dart'; import 'package:comunic/ui/screens/friends_list_screen.dart'; import 'package:comunic/ui/screens/group_screen.dart'; import 'package:comunic/ui/screens/groups_list_screen.dart'; import 'package:comunic/ui/screens/newest_posts.dart'; import 'package:comunic/ui/screens/notifications_screen.dart'; import 'package:comunic/ui/screens/other_friends_lists_screen.dart'; import 'package:comunic/ui/screens/search_screen.dart'; import 'package:comunic/ui/screens/user_access_denied_screen.dart'; import 'package:comunic/ui/screens/user_page_screen.dart'; import 'package:comunic/utils/account_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; /// Abstract main application route /// /// This mixin contains methods available in all display modes /// /// @author Pierre Hubert /// Main controller key statically shared across application /// /// Do not use it directly to avoid context leak, instead use the access method /// [MainController.of] final mainControllerKey = GlobalKey(); mixin MainRoute implements StatefulWidget {} /// Public interface of home controller abstract class MainController extends State { final _pagesStack = List(); /// Default page of the application PageInfo get defaultPage; /// Get the current page being active in the application PageInfo get currentPage => _pagesStack.last; /// Get the current number of page in application stack int get numberOfPages => _pagesStack.length; /// Get current instance of Home controller static MainController of(BuildContext context) { assert(context != null); // A future implementation might need context again return mainControllerKey.currentState; } @override void initState() { super.initState(); _pagesStack.add(defaultPage); } /// Push a new page void pushPage(PageInfo page) => setState(() => _pagesStack.add(page)); /// Pop current page. Do not call this method directly. @protected void doPopPage() { if (_pagesStack.length > 0) setState(() => _pagesStack.removeLast()); } /// Pop until main route is reached void popUntilMainRoute() => Navigator.of(context).popUntil((settings) => ModalRoute.of(context).isCurrent || !ModalRoute.of(context).isActive); /// Open notifications page void openNotificationsPage() => pushPage(PageInfo( type: PageType.NOTIFICATIONS_PAGE, child: NotificationsScreen())); /// Open conversations page void openConversationsPage() => pushPage(PageInfo( type: PageType.CONVERSATIONS_LIST_PAGE, child: ConversationsListScreen())); /// Open latest posts page void openLatestPostsPage() => pushPage( PageInfo(type: PageType.LATEST_POSTS_PAGE, child: NewestPostsScreen())); /// Open user page void openUserPage(int userID) => pushPage(PageInfo( type: PageType.USER_PAGE, child: UserPageScreen(userID: userID), id: userID)); void openUserAccessDeniedPage(int userID) => pushPage(PageInfo(child: UserAccessDeniedScreen(userID: userID))); /// Open current user page void openCurrentUserPage() => this.openUserPage(userID()); /// Open a specific group page specified by its [groupID] void openGroup(int groupID) => pushPage(PageInfo( type: PageType.GROUP_PAGE, child: GroupPageScreen(groupID: groupID), id: groupID)); /// Display the list of friends of current user void openFriendsList() => pushPage( PageInfo(type: PageType.FRIENDS_LIST_PAGE, child: FriendsListScreen())); /// Open search page void openSearchPage() => pushPage(PageInfo(child: SearchScreen())); /// Open groups list page void openGroupsListPage() => pushPage(PageInfo(child: GroupsListScreen())); /// Display the list of friends of a user void openUserFriendsList(int userID) => pushPage(PageInfo(child: OtherUserFriendsListScreen(userID: userID))); /// Push a new widget void push(Widget w, {bool hideNavBar = false, bool canShowAsDialog = false}) => pushPage(PageInfo( child: w, hideNavBar: hideNavBar, canShowAsDialog: canShowAsDialog)); /// Open a conversation void openConversation(int convID, {fullScreen: false}) => pushPage(PageInfo( type: PageType.CONVERSATION_PAGE, child: ConversationRoute(conversationID: convID), hideNavBar: true, )); /// Start a call for a given conversation void startCall(int convID) => pushPage(PageInfo(child: CallScreen(convID: convID), hideNavBar: true)); /// Open account settings void openAccountSettings() => Navigator.of(context) .push(MaterialPageRoute(builder: (c) => AccountSettingsRoute())); /// Open application settings void openAppSettings() => Navigator.of(context) .push(MaterialPageRoute(builder: (c) => AppSettingsRoute())); /// Handle logout requests void requestLogout() async { if (!await showConfirmDialog( context: context, message: tr("Do you really want to sign out from the application ?"), title: tr("Sign out"))) return; popUntilMainRoute(); await AccountHelper().signOut(); Navigator.pushReplacement(context, MaterialPageRoute(builder: (c) { return LoginRoute(); })); } /// Pop current page. Last page can not be popped /// /// If the current route is not the main route, we pop one page void popPage() { if (!ModalRoute.of(context).isCurrent) Navigator.of(context).pop(); else doPopPage(); } }