MasterTabBarController: First step to decouple tab bar item controllers from the tab bar controller. Remove segues and instantiate authentication and unified search controllers programmatically.

This commit is contained in:
SBiOSoftWhare
2021-05-20 21:42:04 +02:00
parent 53ee6a4530
commit ba1ca38c2b
2 changed files with 160 additions and 181 deletions
+153 -173
View File
@@ -49,10 +49,7 @@
// The recents data source shared between all the view controllers of the tab bar.
RecentsDataSource *recentsDataSource;
// The current unified search screen if any
UnifiedSearchViewController *unifiedSearchViewController;
// Current alert (if any).
UIAlertController *currentAlert;
@@ -64,9 +61,6 @@
// The groups data source
GroupsDataSource *groupsDataSource;
// All tabs deinfed in the storyboard
NSArray *initalTabs;
}
@property(nonatomic,getter=isHidden) BOOL hidden;
@@ -77,6 +71,35 @@
@implementation MasterTabBarController
#pragma mark - Properties override
- (HomeViewController *)homeViewController
{
return (HomeViewController*)[self viewControllerForClass:HomeViewController.class];
}
- (FavouritesViewController *)favouritesViewController
{
return (FavouritesViewController*)[self viewControllerForClass:FavouritesViewController.class];
}
- (PeopleViewController *)peopleViewController
{
return (PeopleViewController*)[self viewControllerForClass:PeopleViewController.class];
}
- (RoomsViewController *)roomsViewController
{
return (RoomsViewController*)[self viewControllerForClass:RoomsViewController.class];
}
- (GroupsViewController *)groupsViewController
{
return (GroupsViewController*)[self viewControllerForClass:GroupsViewController.class];
}
#pragma mark - Life cycle
- (void)viewDidLoad
{
[super viewDidLoad];
@@ -86,55 +109,8 @@
// Note: UITabBarViewController shoud not be embed in a UINavigationController (https://github.com/vector-im/riot-ios/issues/3086)
[self vc_removeBackTitle];
// Retrieve the all view controllers
_homeViewController = self.viewControllers[TABBAR_HOME_INDEX];
_favouritesViewController = self.viewControllers[TABBAR_FAVOURITES_INDEX];
_peopleViewController = self.viewControllers[TABBAR_PEOPLE_INDEX];
_roomsViewController = self.viewControllers[TABBAR_ROOMS_INDEX];
_groupsViewController = self.viewControllers[TABBAR_GROUPS_INDEX];
// Set the accessibility labels for all buttons #1842
[_settingsBarButtonItem setAccessibilityLabel:NSLocalizedStringFromTable(@"settings_title", @"Vector", nil)];
[_searchBarButtonIem setAccessibilityLabel:NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil)];
[_homeViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_home", @"Vector", nil)];
[_favouritesViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_favourites", @"Vector", nil)];
[_peopleViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_people", @"Vector", nil)];
[_roomsViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil)];
[_groupsViewController setAccessibilityLabel:NSLocalizedStringFromTable(@"title_groups", @"Vector", nil)];
// Sanity check
NSAssert(_homeViewController && _favouritesViewController && _peopleViewController && _roomsViewController && _groupsViewController, @"Something wrong in Main.storyboard");
// Adjust the display of the icons in the tabbar.
for (UITabBarItem *tabBarItem in self.tabBar.items)
{
if (@available(iOS 13.0, *))
{
// Fix iOS 13 misalignment tab bar images. Some titles are nil and other empty strings. Nil title behaves as if a non-empty title was set.
// Note: However no need to modify imageInsets property on iOS 13.
tabBarItem.title = @"";
}
else
{
tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0);
}
}
childViewControllers = [NSMutableArray array];
// Initialize here the data sources if a matrix session has been already set.
[self initializeDataSources];
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self userInterfaceThemeDidChange];
}];
[self userInterfaceThemeDidChange];
initalTabs = [NSArray arrayWithArray:self.viewControllers];
}
- (void)userInterfaceThemeDidChange
@@ -165,7 +141,16 @@
// Show the tab bar view controller content only when a user is logged in.
self.hidden = ([MXKAccountManager sharedManager].accounts.count == 0);
[self updateTabs];
if (!kThemeServiceDidChangeThemeNotificationObserver)
{
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
[self userInterfaceThemeDidChange];
}];
[self userInterfaceThemeDidChange];
}
}
- (void)viewDidAppear:(BOOL)animated
@@ -231,10 +216,10 @@
[[AppDelegate theDelegate] checkAppVersion];
}
if (unifiedSearchViewController)
if (self.unifiedSearchViewController)
{
[unifiedSearchViewController destroy];
unifiedSearchViewController = nil;
[self.unifiedSearchViewController destroy];
self.unifiedSearchViewController = nil;
}
}
@@ -247,12 +232,6 @@
{
mxSessionArray = nil;
_homeViewController = nil;
_favouritesViewController = nil;
_peopleViewController = nil;
_roomsViewController = nil;
_groupsViewController = nil;
if (currentAlert)
{
[currentAlert dismissViewControllerAnimated:NO completion:nil];
@@ -279,6 +258,30 @@
childViewControllers = nil;
}
#pragma mark - Public
- (void)updateViewControllers:(NSArray<UIViewController*>*)viewControllers
{
self.viewControllers = viewControllers;
[self initializeDataSources];
// Adjust the display of the icons in the tabbar.
for (UITabBarItem *tabBarItem in self.tabBar.items)
{
if (@available(iOS 13.0, *))
{
// Fix iOS 13 misalignment tab bar images. Some titles are nil and other empty strings. Nil title behaves as if a non-empty title was set.
// Note: However no need to modify imageInsets property on iOS 13.
tabBarItem.title = @"";
}
else
{
tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0);
}
}
}
#pragma mark -
- (NSArray*)mxSessions
@@ -297,28 +300,31 @@
// Init the recents data source
recentsDataSource = [[RecentsDataSource alloc] initWithMatrixSession:mainSession];
[_homeViewController displayList:recentsDataSource];
[_favouritesViewController displayList:recentsDataSource];
[_peopleViewController displayList:recentsDataSource];
[_roomsViewController displayList:recentsDataSource];
[self.homeViewController displayList:recentsDataSource];
[self.favouritesViewController displayList:recentsDataSource];
[self.peopleViewController displayList:recentsDataSource];
[self.roomsViewController displayList:recentsDataSource];
// Restore the right delegate of the shared recent data source.
id<MXKDataSourceDelegate> recentsDataSourceDelegate = _homeViewController;
id<MXKDataSourceDelegate> recentsDataSourceDelegate = self.homeViewController;
RecentsDataSourceMode recentsDataSourceMode = RecentsDataSourceModeHome;
switch (self.selectedIndex)
NSInteger tabItemTag = self.tabBar.items[self.selectedIndex].tag;
switch (tabItemTag)
{
case TABBAR_HOME_INDEX:
break;
case TABBAR_FAVOURITES_INDEX:
recentsDataSourceDelegate = _favouritesViewController;
recentsDataSourceDelegate = self.favouritesViewController;
recentsDataSourceMode = RecentsDataSourceModeFavourites;
break;
case TABBAR_PEOPLE_INDEX:
recentsDataSourceDelegate = _peopleViewController;
recentsDataSourceDelegate = self.peopleViewController;
recentsDataSourceMode = RecentsDataSourceModePeople;
break;
case TABBAR_ROOMS_INDEX:
recentsDataSourceDelegate = _roomsViewController;
recentsDataSourceDelegate = self.roomsViewController;
recentsDataSourceMode = RecentsDataSourceModeRooms;
break;
@@ -330,7 +336,7 @@
// Init the recents data source
groupsDataSource = [[GroupsDataSource alloc] initWithMatrixSession:mainSession];
[groupsDataSource finalizeInitialization];
[_groupsViewController displayList:groupsDataSource];
[self.groupsViewController displayList:groupsDataSource];
// Check whether there are others sessions
NSArray* mxSessions = self.mxSessions;
@@ -351,7 +357,7 @@
- (void)addMatrixSession:(MXSession *)mxSession
{
// Check whether the controller'€™s view is loaded into memory.
if (_homeViewController)
if (self.homeViewController)
{
// Check whether the data sources have been initialized.
if (!recentsDataSource)
@@ -396,10 +402,10 @@
// Remove matrix sessions observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionStateDidChangeNotification object:nil];
[_homeViewController displayList:nil];
[_favouritesViewController displayList:nil];
[_peopleViewController displayList:nil];
[_roomsViewController displayList:nil];
[self.homeViewController displayList:nil];
[self.favouritesViewController displayList:nil];
[self.peopleViewController displayList:nil];
[self.roomsViewController displayList:nil];
[recentsDataSource destroy];
recentsDataSource = nil;
@@ -415,6 +421,53 @@
[self refreshTabBarBadges];
}
// TODO: Move authentication presentation in an AuthenticationCoordinator managed at AppCoordinator level
- (void)presentAuthenticationViewController
{
AuthenticationViewController *authenticationViewController = [AuthenticationViewController authenticationViewController];
authenticationViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:authenticationViewController animated:YES completion:nil];
// Keep ref on the authentification view controller while it is displayed
// ie until we get the notification about a new account
_authViewController = authenticationViewController;
isAuthViewControllerPreparing = NO;
// Listen to the end of the authentication flow
_authViewController.authVCDelegate = self;
authViewControllerObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidAddAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
_authViewController = nil;
[[NSNotificationCenter defaultCenter] removeObserver:authViewControllerObserver];
authViewControllerObserver = nil;
}];
authViewRemovedAccountObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidRemoveAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
// The user has cleared data for their soft logged out account
_authViewController = nil;
[[NSNotificationCenter defaultCenter] removeObserver:authViewRemovedAccountObserver];
authViewRemovedAccountObserver = nil;
}];
// Forward parameters if any
if (authViewControllerRegistrationParameters)
{
_authViewController.externalRegistrationParameters = authViewControllerRegistrationParameters;
authViewControllerRegistrationParameters = nil;
}
if (softLogoutCredentials)
{
_authViewController.softLogoutCredentials = softLogoutCredentials;
softLogoutCredentials = nil;
}
}
- (void)showAuthenticationScreen
{
NSLog(@"[MasterTabBarController] showAuthenticationScreen");
@@ -428,9 +481,8 @@
[self resetReviewSessionsFlags];
[[AppDelegate theDelegate] restoreInitialDisplay:^{
[self performSegueWithIdentifier:@"showAuth" sender:self];
[self presentAuthenticationViewController];
}];
}
}
@@ -474,8 +526,7 @@
[[AppDelegate theDelegate] restoreInitialDisplay:^{
[self performSegueWithIdentifier:@"showAuth" sender:self];
[self presentAuthenticationViewController];
}];
}
}
@@ -651,18 +702,6 @@
[self releaseCurrentDetailsViewController];
}
- (void)dismissUnifiedSearch:(BOOL)animated completion:(void (^)(void))completion
{
if (unifiedSearchViewController)
{
[self.navigationController dismissViewControllerAnimated:animated completion:completion];
}
else if (completion)
{
completion();
}
}
- (NSUInteger)missedDiscussionsCount
{
NSUInteger roomCount = 0;
@@ -688,66 +727,29 @@
return roomCount;
}
#pragma mark -
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
- (UIViewController*)viewControllerForClass:(Class)klass
{
// Keep ref on destinationViewController
[childViewControllers addObject:segue.destinationViewController];
UIViewController *foundViewController;
if ([[segue identifier] isEqualToString:@"showAuth"])
NSInteger viewControllerIndex = [self.viewControllers indexOfObjectPassingTest:^BOOL(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:klass])
{
*stop = YES;
return YES;
}
return NO;
}];
if (viewControllerIndex != NSNotFound)
{
// Keep ref on the authentification view controller while it is displayed
// ie until we get the notification about a new account
_authViewController = segue.destinationViewController;
isAuthViewControllerPreparing = NO;
// Listen to the end of the authentication flow
_authViewController.authVCDelegate = self;
authViewControllerObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidAddAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
_authViewController = nil;
[[NSNotificationCenter defaultCenter] removeObserver:authViewControllerObserver];
authViewControllerObserver = nil;
}];
authViewRemovedAccountObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidRemoveAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
// The user has cleared data for their soft logged out account
_authViewController = nil;
[[NSNotificationCenter defaultCenter] removeObserver:authViewRemovedAccountObserver];
authViewRemovedAccountObserver = nil;
}];
// Forward parameters if any
if (authViewControllerRegistrationParameters)
{
_authViewController.externalRegistrationParameters = authViewControllerRegistrationParameters;
authViewControllerRegistrationParameters = nil;
}
if (softLogoutCredentials)
{
_authViewController.softLogoutCredentials = softLogoutCredentials;
softLogoutCredentials = nil;
}
}
else if ([[segue identifier] isEqualToString:@"showUnifiedSearch"])
{
unifiedSearchViewController= segue.destinationViewController;
for (MXSession *session in mxSessionArray)
{
[unifiedSearchViewController addMatrixSession:session];
}
foundViewController = self.viewControllers[viewControllerIndex];
}
// Hide back button title
self.navigationController.topViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
return foundViewController;
}
#pragma mark -
/**
Load the data source of the room to open.
@@ -756,8 +758,8 @@
- (void)dataSourceOfRoomToDisplay:(void (^)(MXKRoomDataSource *roomDataSource))onComplete
{
// Check whether an event has been selected from messages or files search tab.
MXEvent *selectedSearchEvent = unifiedSearchViewController.selectedSearchEvent;
MXSession *selectedSearchEventSession = unifiedSearchViewController.selectedSearchEventSession;
MXEvent *selectedSearchEvent = self.unifiedSearchViewController.selectedSearchEvent;
MXSession *selectedSearchEventSession = self.unifiedSearchViewController.selectedSearchEventSession;
if (!selectedSearchEvent)
{
@@ -887,28 +889,6 @@
#pragma mark -
- (void)updateTabs
{
NSMutableArray *newTabs = [NSMutableArray arrayWithArray:initalTabs];
if (!RiotSettings.shared.homeScreenShowCommunitiesTab)
{
[newTabs removeObjectAtIndex:TABBAR_GROUPS_INDEX];
}
if (!RiotSettings.shared.homeScreenShowRoomsTab)
{
[newTabs removeObjectAtIndex:TABBAR_ROOMS_INDEX];
}
if (!RiotSettings.shared.homeScreenShowPeopleTab)
{
[newTabs removeObjectAtIndex:TABBAR_PEOPLE_INDEX];
}
if (!RiotSettings.shared.homeScreenShowFavouritesTab)
{
[newTabs removeObjectAtIndex:TABBAR_FAVOURITES_INDEX];
}
self.viewControllers = newTabs;
}
- (void)refreshTabBarBadges
{
// Use a middle dot to signal missed notif in favourites