2017-03-23 16:48:05 +00:00
/ *
Copyright 2017 Vector Creations Ltd
2018-07-23 16:06:53 +00:00
Copyright 2018 New Vector Ltd
2017-03-23 16:48:05 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : // www . apache . org / licenses / LICENSE -2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
# import "MasterTabBarController.h"
# import "UnifiedSearchViewController.h"
# import "RecentsDataSource.h"
2017-12-12 15:03:26 +00:00
# import "GroupsDataSource.h"
2017-03-23 16:48:05 +00:00
# import "AppDelegate.h"
2017-04-18 13:55:51 +00:00
# import "MXRoom+Riot.h"
2017-08-22 07:46:53 +00:00
# import "MXSession+Riot.h"
2017-04-18 13:55:51 +00:00
2018-07-02 12:51:47 +00:00
# import "Riot-Swift.h"
2017-03-23 16:48:05 +00:00
@ interface MasterTabBarController ( )
{
// Array of ` MXSession` instances .
NSMutableArray * mxSessionArray ;
// Tell whether the authentication screen is preparing .
BOOL isAuthViewControllerPreparing ;
// Observer that checks when the Authentification view controller has gone .
id authViewControllerObserver ;
2019-07-23 14:20:07 +00:00
id authViewRemovedAccountObserver ;
2017-03-23 16:48:05 +00:00
// The parameters to pass to the Authentification view controller .
NSDictionary * authViewControllerRegistrationParameters ;
2019-07-19 12:25:45 +00:00
MXCredentials * softLogoutCredentials ;
2017-03-23 16:48:05 +00:00
2017-04-06 12:27:45 +00:00
// The recents data source shared between all the view controllers of the tab bar .
RecentsDataSource * recentsDataSource ;
2017-03-23 16:48:05 +00:00
// The current unified search screen if any
UnifiedSearchViewController * unifiedSearchViewController ;
// Current alert ( if any ) .
2017-07-14 14:41:25 +00:00
UIAlertController * currentAlert ;
2017-07-21 09:28:17 +00:00
// Keep reference on the pushed view controllers to release them correctly
NSMutableArray * childViewControllers ;
2017-08-11 14:56:09 +00:00
2019-01-11 09:32:56 +00:00
// Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change .
id kThemeServiceDidChangeThemeNotificationObserver ;
2017-12-12 15:03:26 +00:00
// The groups data source
GroupsDataSource * groupsDataSource ;
2017-03-23 16:48:05 +00:00
}
2017-04-27 10:37:29 +00:00
@ property ( nonatomic , getter = isHidden ) BOOL hidden ;
2017-03-23 16:48:05 +00:00
@ end
@ implementation MasterTabBarController
- ( void ) viewDidLoad
{
[ super viewDidLoad ] ;
// Do any additional setup after loading the view , typically from a nib .
2017-04-06 12:27:45 +00:00
// Retrieve the all view controllers
2019-01-07 23:24:11 +00:00
_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 ] ;
2017-04-06 12:27:45 +00:00
2018-06-20 08:51:44 +00:00
// Set the accessibility labels for all buttons #1842
2018-06-25 13:07:54 +00:00
[ _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 ) ] ;
2018-06-20 08:51:44 +00:00
2017-04-06 12:27:45 +00:00
// Sanity check
2017-12-12 15:03:26 +00:00
NSAssert ( _homeViewController && _favouritesViewController && _peopleViewController && _roomsViewController && _groupsViewController , @ "Something wrong in Main.storyboard" ) ;
2017-08-11 14:56:09 +00:00
2017-04-14 15:01:44 +00:00
// Adjust the display of the icons in the tabbar .
for ( UITabBarItem * tabBarItem in self . tabBar . items )
{
2019-11-06 14:32:42 +00:00
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 ) ;
}
2017-04-14 15:01:44 +00:00
}
2017-07-21 09:28:17 +00:00
childViewControllers = [ NSMutableArray array ] ;
2017-03-23 16:48:05 +00:00
// Initialize here the data sources if a matrix session has been already set .
[ self initializeDataSources ] ;
2017-08-11 14:56:09 +00:00
// Observe user interface theme change .
2019-01-11 09:32:56 +00:00
kThemeServiceDidChangeThemeNotificationObserver = [ [ NSNotificationCenter defaultCenter ] addObserverForName : kThemeServiceDidChangeThemeNotification object : nil queue : [ NSOperationQueue mainQueue ] usingBlock : ^ ( NSNotification * notif ) {
2017-08-11 14:56:09 +00:00
[ self userInterfaceThemeDidChange ] ;
} ] ;
[ self userInterfaceThemeDidChange ] ;
}
- ( void ) userInterfaceThemeDidChange
{
2019-01-11 10:45:27 +00:00
[ ThemeService . shared . theme applyStyleOnNavigationBar : self . navigationController . navigationBar ] ;
2018-11-29 16:31:41 +00:00
2019-02-19 08:39:01 +00:00
[ ThemeService . shared . theme applyStyleOnTabBar : self . tabBar ] ;
2017-08-11 14:56:09 +00:00
2019-01-11 10:45:27 +00:00
self . view . backgroundColor = ThemeService . shared . theme . backgroundColor ;
2017-08-11 14:56:09 +00:00
[ self setNeedsStatusBarAppearanceUpdate ] ;
}
- ( UIStatusBarStyle ) preferredStatusBarStyle
{
2019-01-11 10:45:27 +00:00
return ThemeService . shared . theme . statusBarStyle ;
2017-03-23 16:48:05 +00:00
}
2017-04-27 10:37:29 +00:00
- ( void ) viewWillAppear : ( BOOL ) animated
{
[ super viewWillAppear : animated ] ;
// Show the tab bar view controller content only when a user is logged in .
self . hidden = ( [ MXKAccountManager sharedManager ] . accounts . count = = 0 ) ;
}
2017-03-23 16:48:05 +00:00
- ( void ) viewDidAppear : ( BOOL ) animated
{
2017-10-30 15:39:58 +00:00
NSLog ( @ "[MasterTabBarController] viewDidAppear" ) ;
2017-03-23 16:48:05 +00:00
[ super viewDidAppear : animated ] ;
// Check whether we ' re not logged in
2019-07-19 12:25:45 +00:00
BOOL authIsShown = NO ;
2017-03-23 16:48:05 +00:00
if ( ! [ MXKAccountManager sharedManager ] . accounts . count )
{
[ self showAuthenticationScreen ] ;
2019-07-19 12:25:45 +00:00
authIsShown = YES ;
2017-03-23 16:48:05 +00:00
}
2019-07-19 12:25:45 +00:00
else if ( ! [ MXKAccountManager sharedManager ] . activeAccounts . count )
{
// Display a login screen if the account is soft logout
// Note : We support only one account
MXKAccount * account = [ MXKAccountManager sharedManager ] . accounts . firstObject ;
if ( account . isSoftLogout )
{
[ self showAuthenticationScreenAfterSoftLogout : account . mxCredentials ] ;
authIsShown = YES ;
}
}
if ( ! authIsShown )
2017-03-23 16:48:05 +00:00
{
// Check whether the user has been already prompted to send crash reports .
2018-07-02 12:51:47 +00:00
// ( Check whether ' enableCrashReport ' flag has been set once )
2018-07-02 16:04:52 +00:00
if ( ! RiotSettings . shared . isEnableCrashReportHasBeenSetOnce )
2017-03-23 16:48:05 +00:00
{
2018-06-27 08:43:22 +00:00
[ self promptUserBeforeUsingAnalytics ] ;
2017-03-23 16:48:05 +00:00
}
2017-04-14 15:01:44 +00:00
2017-04-28 12:06:58 +00:00
[ self refreshTabBarBadges ] ;
2017-07-21 09:28:17 +00:00
// Release properly pushed and / or presented view controller
if ( childViewControllers . count )
{
for ( id viewController in childViewControllers )
{
if ( [ viewController isKindOfClass : [ UINavigationController class ] ] )
{
UINavigationController * navigationController = ( UINavigationController * ) viewController ;
for ( id subViewController in navigationController . viewControllers )
{
if ( [ subViewController respondsToSelector : @ selector ( destroy ) ] )
{
[ subViewController destroy ] ;
}
}
}
else if ( [ viewController respondsToSelector : @ selector ( destroy ) ] )
{
[ viewController destroy ] ;
}
}
[ childViewControllers removeAllObjects ] ;
}
2017-03-23 16:48:05 +00:00
}
if ( unifiedSearchViewController )
{
[ unifiedSearchViewController destroy ] ;
unifiedSearchViewController = nil ;
}
}
2017-04-14 15:01:44 +00:00
- ( void ) viewDidDisappear : ( BOOL ) animated
{
[ super viewDidDisappear : animated ] ;
}
2017-03-23 16:48:05 +00:00
- ( void ) dealloc
{
mxSessionArray = nil ;
_homeViewController = nil ;
2017-04-06 12:27:45 +00:00
_favouritesViewController = nil ;
_peopleViewController = nil ;
_roomsViewController = nil ;
2017-12-12 15:03:26 +00:00
_groupsViewController = nil ;
2017-03-23 16:48:05 +00:00
if ( currentAlert )
{
2017-07-14 14:41:25 +00:00
[ currentAlert dismissViewControllerAnimated : NO completion : nil ] ;
2017-03-23 16:48:05 +00:00
currentAlert = nil ;
}
if ( authViewControllerObserver )
{
[ [ NSNotificationCenter defaultCenter ] removeObserver : authViewControllerObserver ] ;
authViewControllerObserver = nil ;
}
2019-07-23 14:20:07 +00:00
if ( authViewRemovedAccountObserver )
{
[ [ NSNotificationCenter defaultCenter ] removeObserver : authViewRemovedAccountObserver ] ;
authViewRemovedAccountObserver = nil ;
}
2017-07-21 09:28:17 +00:00
2019-01-11 09:32:56 +00:00
if ( kThemeServiceDidChangeThemeNotificationObserver )
2017-08-11 14:56:09 +00:00
{
2019-01-11 09:32:56 +00:00
[ [ NSNotificationCenter defaultCenter ] removeObserver : kThemeServiceDidChangeThemeNotificationObserver ] ;
kThemeServiceDidChangeThemeNotificationObserver = nil ;
2017-08-11 14:56:09 +00:00
}
2017-07-21 09:28:17 +00:00
childViewControllers = nil ;
2017-03-23 16:48:05 +00:00
}
# pragma mark -
- ( NSArray * ) mxSessions
{
return [ NSArray arrayWithArray : mxSessionArray ] ;
}
- ( void ) initializeDataSources
{
MXSession * mainSession = mxSessionArray . firstObject ;
if ( mainSession )
{
2017-06-14 15:30:01 +00:00
NSLog ( @ "[MasterTabBarController] initializeDataSources" ) ;
2017-03-23 16:48:05 +00:00
// Init the recents data source
2017-04-06 12:27:45 +00:00
recentsDataSource = [ [ RecentsDataSource alloc ] initWithMatrixSession : mainSession ] ;
[ _homeViewController displayList : recentsDataSource ] ;
[ _favouritesViewController displayList : recentsDataSource ] ;
2017-04-11 07:36:22 +00:00
[ _peopleViewController displayList : recentsDataSource ] ;
2017-04-06 12:27:45 +00:00
[ _roomsViewController displayList : recentsDataSource ] ;
2017-03-23 16:48:05 +00:00
2017-06-14 15:30:01 +00:00
// Restore the right delegate of the shared recent data source .
id < MXKDataSourceDelegate > recentsDataSourceDelegate = _homeViewController ;
RecentsDataSourceMode recentsDataSourceMode = RecentsDataSourceModeHome ;
switch ( self . selectedIndex )
{
case TABBAR_HOME _INDEX :
break ;
case TABBAR_FAVOURITES _INDEX :
recentsDataSourceDelegate = _favouritesViewController ;
recentsDataSourceMode = RecentsDataSourceModeFavourites ;
break ;
case TABBAR_PEOPLE _INDEX :
recentsDataSourceDelegate = _peopleViewController ;
recentsDataSourceMode = RecentsDataSourceModePeople ;
break ;
case TABBAR_ROOMS _INDEX :
recentsDataSourceDelegate = _roomsViewController ;
recentsDataSourceMode = RecentsDataSourceModeRooms ;
break ;
default :
break ;
}
[ recentsDataSource setDelegate : recentsDataSourceDelegate andRecentsDataSourceMode : recentsDataSourceMode ] ;
2017-12-12 15:03:26 +00:00
// Init the recents data source
groupsDataSource = [ [ GroupsDataSource alloc ] initWithMatrixSession : mainSession ] ;
[ groupsDataSource finalizeInitialization ] ;
[ _groupsViewController displayList : groupsDataSource ] ;
2017-03-23 16:48:05 +00:00
// Check whether there are others sessions
NSArray * mxSessions = self . mxSessions ;
if ( mxSessions . count > 1 )
{
for ( MXSession * mxSession in mxSessions )
{
if ( mxSession ! = mainSession )
{
// Add the session to the recents data source
2017-04-06 12:27:45 +00:00
[ recentsDataSource addMatrixSession : mxSession ] ;
2017-03-23 16:48:05 +00:00
}
}
}
}
}
- ( void ) addMatrixSession : ( MXSession * ) mxSession
{
// Check whether the controller ' s view is loaded into memory .
if ( _homeViewController )
{
// Check whether the data sources have been initialized .
2017-04-06 12:27:45 +00:00
if ( ! recentsDataSource )
2017-03-23 16:48:05 +00:00
{
// Add first the session . The updated sessions list will be used during data sources initialization .
mxSessionArray = [ NSMutableArray array ] ;
[ mxSessionArray addObject : mxSession ] ;
// Prepare data sources and return
[ self initializeDataSources ] ;
return ;
}
else
{
2017-04-06 12:27:45 +00:00
// Add the session to the existing data sources
[ recentsDataSource addMatrixSession : mxSession ] ;
2017-03-23 16:48:05 +00:00
}
}
if ( ! mxSessionArray )
{
mxSessionArray = [ NSMutableArray array ] ;
2017-04-18 13:55:51 +00:00
// Add matrix sessions observer on first added session
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( onMatrixSessionStateDidChange : ) name : kMXSessionStateDidChangeNotification object : nil ] ;
2017-03-23 16:48:05 +00:00
}
[ mxSessionArray addObject : mxSession ] ;
2017-12-12 15:03:26 +00:00
// @ TODO : handle multi sessions for groups
2017-03-23 16:48:05 +00:00
}
- ( void ) removeMatrixSession : ( MXSession * ) mxSession
{
2017-04-06 12:27:45 +00:00
[ recentsDataSource removeMatrixSession : mxSession ] ;
2017-03-23 16:48:05 +00:00
// Check whether there are others sessions
2017-04-06 12:27:45 +00:00
if ( ! recentsDataSource . mxSessions . count )
2017-03-23 16:48:05 +00:00
{
2017-04-18 13:55:51 +00:00
// Remove matrix sessions observer
[ [ NSNotificationCenter defaultCenter ] removeObserver : self name : kMXSessionStateDidChangeNotification object : nil ] ;
2017-03-23 16:48:05 +00:00
[ _homeViewController displayList : nil ] ;
2017-04-06 12:27:45 +00:00
[ _favouritesViewController displayList : nil ] ;
2017-04-11 07:36:22 +00:00
[ _peopleViewController displayList : nil ] ;
2017-04-06 12:27:45 +00:00
[ _roomsViewController displayList : nil ] ;
[ recentsDataSource destroy ] ;
recentsDataSource = nil ;
2017-03-23 16:48:05 +00:00
}
[ mxSessionArray removeObject : mxSession ] ;
2017-12-12 15:03:26 +00:00
// @ TODO : handle multi sessions for groups
2017-03-23 16:48:05 +00:00
}
2017-04-18 13:55:51 +00:00
- ( void ) onMatrixSessionStateDidChange : ( NSNotification * ) notif
{
2017-04-28 12:06:58 +00:00
[ self refreshTabBarBadges ] ;
2017-04-18 13:55:51 +00:00
}
2017-03-23 16:48:05 +00:00
- ( void ) showAuthenticationScreen
{
2017-10-30 15:39:58 +00:00
NSLog ( @ "[MasterTabBarController] showAuthenticationScreen" ) ;
2017-03-23 16:48:05 +00:00
// Check whether an authentication screen is not already shown or preparing
if ( ! self . authViewController && ! isAuthViewControllerPreparing )
{
isAuthViewControllerPreparing = YES ;
[ [ AppDelegate theDelegate ] restoreInitialDisplay : ^ {
[ self performSegueWithIdentifier : @ "showAuth" sender : self ] ;
} ] ;
}
}
- ( void ) showAuthenticationScreenWithRegistrationParameters : ( NSDictionary * ) parameters
{
if ( self . authViewController )
{
NSLog ( @ "[MasterTabBarController] Universal link: Forward registration parameter to the existing AuthViewController" ) ;
self . authViewController . externalRegistrationParameters = parameters ;
}
else
{
2018-04-17 19:39:31 +00:00
NSLog ( @ "[MasterTabBarController] Universal link: Prompt to logout current sessions and open AuthViewController to complete the registration" ) ;
2017-03-23 16:48:05 +00:00
// Keep a ref on the params
authViewControllerRegistrationParameters = parameters ;
2018-04-17 19:39:31 +00:00
// Prompt to logout . It will then display AuthViewController if the user is logged out .
[ [ AppDelegate theDelegate ] logoutWithConfirmation : YES completion : ^ ( BOOL isLoggedOut ) {
if ( ! isLoggedOut )
{
// Reset temporary params
authViewControllerRegistrationParameters = nil ;
}
} ] ;
2017-03-23 16:48:05 +00:00
}
}
2019-07-19 12:25:45 +00:00
- ( void ) showAuthenticationScreenAfterSoftLogout : ( MXCredentials * ) credentials ;
{
NSLog ( @ "[MasterTabBarController] showAuthenticationScreenAfterSoftLogout" ) ;
softLogoutCredentials = credentials ;
// Check whether an authentication screen is not already shown or preparing
if ( ! self . authViewController && ! isAuthViewControllerPreparing )
{
isAuthViewControllerPreparing = YES ;
[ [ AppDelegate theDelegate ] restoreInitialDisplay : ^ {
[ self performSegueWithIdentifier : @ "showAuth" sender : self ] ;
} ] ;
}
}
2017-03-23 16:48:05 +00:00
- ( void ) selectRoomWithId : ( NSString * ) roomId andEventId : ( NSString * ) eventId inMatrixSession : ( MXSession * ) matrixSession
2018-08-27 15:14:28 +00:00
{
[ self selectRoomWithId : roomId andEventId : eventId inMatrixSession : matrixSession completion : nil ] ;
}
- ( void ) selectRoomWithId : ( NSString * ) roomId andEventId : ( NSString * ) eventId inMatrixSession : ( MXSession * ) matrixSession completion : ( void ( ^ ) ( void ) ) completion
2017-03-23 16:48:05 +00:00
{
if ( _selectedRoomId && [ _selectedRoomId isEqualToString : roomId ]
&& _selectedEventId && [ _selectedEventId isEqualToString : eventId ]
&& _selectedRoomSession && _selectedRoomSession = = matrixSession )
{
// Nothing to do
2018-08-27 15:14:28 +00:00
if ( completion )
{
completion ( ) ;
}
2017-03-23 16:48:05 +00:00
return ;
}
_selectedRoomId = roomId ;
_selectedEventId = eventId ;
_selectedRoomSession = matrixSession ;
if ( roomId && matrixSession )
{
2018-08-09 14:30:31 +00:00
// Preload the data source before performing the segue
MXWeakify ( self ) ;
[ self dataSourceOfRoomToDisplay : ^ ( MXKRoomDataSource * roomDataSource ) {
MXStrongifyAndReturnIfNil ( self ) ;
2018-08-27 15:14:28 +00:00
2018-08-09 14:30:31 +00:00
self -> _selectedRoomDataSource = roomDataSource ;
2018-08-27 15:14:28 +00:00
2018-08-09 14:30:31 +00:00
[ self performSegueWithIdentifier : @ "showRoomDetails" sender : self ] ;
2018-08-27 15:14:28 +00:00
if ( completion )
{
completion ( ) ;
}
2018-08-09 14:30:31 +00:00
} ] ;
2017-03-23 16:48:05 +00:00
}
else
{
2017-03-28 15:26:50 +00:00
[ self releaseSelectedItem ] ;
2018-08-27 15:14:28 +00:00
if ( completion )
{
completion ( ) ;
}
2017-03-23 16:48:05 +00:00
}
}
- ( void ) showRoomPreview : ( RoomPreviewData * ) roomPreviewData
{
_selectedRoomPreviewData = roomPreviewData ;
_selectedRoomId = roomPreviewData . roomId ;
_selectedRoomSession = roomPreviewData . mxSession ;
2017-03-28 15:26:50 +00:00
[ self performSegueWithIdentifier : @ "showRoomDetails" sender : self ] ;
2017-03-23 16:48:05 +00:00
}
2017-03-28 15:26:50 +00:00
- ( void ) selectContact : ( MXKContact * ) contact
{
_selectedContact = contact ;
[ self performSegueWithIdentifier : @ "showContactDetails" sender : self ] ;
}
2017-12-12 15:03:26 +00:00
- ( void ) selectGroup : ( MXGroup * ) group inMatrixSession : ( MXSession * ) matrixSession
{
_selectedGroup = group ;
_selectedGroupSession = matrixSession ;
[ self performSegueWithIdentifier : @ "showGroupDetails" sender : self ] ;
}
2017-03-28 15:26:50 +00:00
- ( void ) releaseSelectedItem
2017-03-23 16:48:05 +00:00
{
_selectedRoomId = nil ;
_selectedEventId = nil ;
_selectedRoomSession = nil ;
2018-08-09 14:30:31 +00:00
_selectedRoomDataSource = nil ;
_selectedRoomPreviewData = nil ;
2017-03-23 16:48:05 +00:00
2017-03-28 15:26:50 +00:00
_selectedContact = nil ;
2017-12-12 15:03:26 +00:00
_selectedGroup = nil ;
_selectedGroupSession = nil ;
2017-12-22 13:33:40 +00:00
[ self releaseCurrentDetailsViewController ] ;
2017-03-23 16:48:05 +00:00
}
2017-03-24 16:19:55 +00:00
- ( void ) dismissUnifiedSearch : ( BOOL ) animated completion : ( void ( ^ ) ( void ) ) completion
{
if ( unifiedSearchViewController )
2017-03-23 16:48:05 +00:00
{
2017-03-24 16:19:55 +00:00
[ self . navigationController dismissViewControllerAnimated : animated completion : completion ] ;
}
else if ( completion )
{
completion ( ) ;
2017-03-23 16:48:05 +00:00
}
}
2017-04-18 13:55:51 +00:00
- ( NSUInteger ) missedDiscussionsCount
{
NSUInteger roomCount = 0 ;
// Considering all the current sessions .
for ( MXSession * session in mxSessionArray )
{
2017-08-22 07:46:53 +00:00
roomCount + = [ session riot_missedDiscussionsCount ] ;
2017-04-18 13:55:51 +00:00
}
return roomCount ;
}
- ( NSUInteger ) missedHighlightDiscussionsCount
{
NSUInteger roomCount = 0 ;
for ( MXSession * session in mxSessionArray )
{
roomCount + = [ session missedHighlightDiscussionsCount ] ;
}
return roomCount ;
}
2017-03-24 16:19:55 +00:00
# pragma mark -
2017-03-23 16:48:05 +00:00
- ( void ) prepareForSegue : ( UIStoryboardSegue * ) segue sender : ( id ) sender
{
2017-12-12 15:03:26 +00:00
if ( [ [ segue identifier ] isEqualToString : @ "showRoomDetails" ] || [ [ segue identifier ] isEqualToString : @ "showContactDetails" ] || [ [ segue identifier ] isEqualToString : @ "showGroupDetails" ] )
2017-03-23 16:48:05 +00:00
{
2017-03-28 15:26:50 +00:00
UINavigationController * navigationController = [ segue destinationViewController ] ;
2017-12-22 13:33:40 +00:00
[ self releaseCurrentDetailsViewController ] ;
2017-03-23 16:48:05 +00:00
2017-03-28 15:26:50 +00:00
if ( [ [ segue identifier ] isEqualToString : @ "showRoomDetails" ] )
2017-03-23 16:48:05 +00:00
{
2018-08-09 14:30:31 +00:00
if ( _selectedRoomPreviewData )
{
// Replace the rootviewcontroller with a room view controller
// Get the RoomViewController from the storyboard
UIStoryboard * storyboard = [ UIStoryboard storyboardWithName : @ "Main" bundle : [ NSBundle mainBundle ] ] ;
_currentRoomViewController = [ storyboard instantiateViewControllerWithIdentifier : @ "RoomViewControllerStoryboardId" ] ;
navigationController . viewControllers = @ [ _currentRoomViewController ] ;
[ _currentRoomViewController displayRoomPreview : _selectedRoomPreviewData ] ;
_selectedRoomPreviewData = nil ;
[ self setupLeftBarButtonItem ] ;
}
else
2017-03-23 16:48:05 +00:00
{
2018-07-20 08:43:04 +00:00
MXWeakify ( self ) ;
2018-08-09 14:30:31 +00:00
void ( ^ openRoomDataSource ) ( MXKRoomDataSource * roomDataSource ) = ^ ( MXKRoomDataSource * roomDataSource ) {
2018-07-20 08:43:04 +00:00
MXStrongifyAndReturnIfNil ( self ) ;
// Replace the rootviewcontroller with a room view controller
// Get the RoomViewController from the storyboard
UIStoryboard * storyboard = [ UIStoryboard storyboardWithName : @ "Main" bundle : [ NSBundle mainBundle ] ] ;
self -> _currentRoomViewController = [ storyboard instantiateViewControllerWithIdentifier : @ "RoomViewControllerStoryboardId" ] ;
navigationController . viewControllers = @ [ self . currentRoomViewController ] ;
[ self . currentRoomViewController displayRoom : roomDataSource ] ;
2018-07-23 16:06:53 +00:00
[ self setupLeftBarButtonItem ] ;
2018-07-20 08:43:04 +00:00
2018-08-09 14:30:31 +00:00
} ;
2018-07-23 16:06:53 +00:00
2018-08-09 14:30:31 +00:00
if ( _selectedRoomDataSource )
{
// If the room data source is already loaded , display it
openRoomDataSource ( _selectedRoomDataSource ) ;
_selectedRoomDataSource = nil ;
}
else
{
// Else , load it . The user may see the EmptyDetailsViewControllerStoryboardId
// screen in this case
[ self dataSourceOfRoomToDisplay : ^ ( MXKRoomDataSource * roomDataSource ) {
openRoomDataSource ( roomDataSource ) ;
} ] ;
}
2017-03-23 16:48:05 +00:00
}
}
2017-12-12 15:03:26 +00:00
else if ( [ [ segue identifier ] isEqualToString : @ "showContactDetails" ] )
2017-03-28 15:26:50 +00:00
{
// Replace the rootviewcontroller with a contact details view controller
_currentContactDetailViewController = [ ContactDetailsViewController contactDetailsViewController ] ;
_currentContactDetailViewController . enableVoipCall = NO ;
_currentContactDetailViewController . contact = _selectedContact ;
navigationController . viewControllers = @ [ _currentContactDetailViewController ] ;
2018-07-23 16:06:53 +00:00
[ self setupLeftBarButtonItem ] ;
2017-03-28 15:26:50 +00:00
}
2017-12-12 15:03:26 +00:00
else
{
// Replace the rootviewcontroller with a group details view controller
_currentGroupDetailViewController = [ GroupDetailsViewController groupDetailsViewController ] ;
2017-12-14 15:05:11 +00:00
[ _currentGroupDetailViewController setGroup : _selectedGroup withMatrixSession : _selectedGroupSession ] ;
2017-12-12 15:03:26 +00:00
navigationController . viewControllers = @ [ _currentGroupDetailViewController ] ;
2018-07-23 16:06:53 +00:00
[ self setupLeftBarButtonItem ] ;
2017-03-23 16:48:05 +00:00
}
}
else
{
// Keep ref on destinationViewController
2017-07-21 09:28:17 +00:00
[ childViewControllers addObject : segue . destinationViewController ] ;
2017-03-23 16:48:05 +00:00
if ( [ [ segue identifier ] isEqualToString : @ "showAuth" ] )
{
// 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 ;
authViewControllerObserver = [ [ NSNotificationCenter defaultCenter ] addObserverForName : kMXKAccountManagerDidAddAccountNotification object : nil queue : [ NSOperationQueue mainQueue ] usingBlock : ^ ( NSNotification * notif ) {
_authViewController = nil ;
[ [ NSNotificationCenter defaultCenter ] removeObserver : authViewControllerObserver ] ;
authViewControllerObserver = nil ;
} ] ;
2019-07-23 14:20:07 +00:00
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 ;
} ] ;
2017-03-23 16:48:05 +00:00
// Forward parameters if any
if ( authViewControllerRegistrationParameters )
{
_authViewController . externalRegistrationParameters = authViewControllerRegistrationParameters ;
authViewControllerRegistrationParameters = nil ;
}
2019-07-19 12:25:45 +00:00
if ( softLogoutCredentials )
{
_authViewController . softLogoutCredentials = softLogoutCredentials ;
softLogoutCredentials = nil ;
}
2017-03-23 16:48:05 +00:00
}
else if ( [ [ segue identifier ] isEqualToString : @ "showUnifiedSearch" ] )
{
unifiedSearchViewController = segue . destinationViewController ;
for ( MXSession * session in mxSessionArray )
{
[ unifiedSearchViewController addMatrixSession : session ] ;
}
}
}
2017-03-28 15:26:50 +00:00
// Hide back button title
2017-03-28 16:17:14 +00:00
self . navigationController . topViewController . navigationItem . backBarButtonItem = [ [ UIBarButtonItem alloc ] initWithTitle : @ "" style : UIBarButtonItemStylePlain target : nil action : nil ] ;
2017-03-23 16:48:05 +00:00
}
2018-07-20 08:43:04 +00:00
/ * *
Load the data source of the room to open .
@ param onComplete a block providing the loaded room data source .
* /
- ( 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 ;
if ( ! selectedSearchEvent )
{
if ( ! _selectedEventId )
{
// LIVE : Show the room live timeline managed by MXKRoomDataSourceManager
MXKRoomDataSourceManager * roomDataSourceManager = [ MXKRoomDataSourceManager sharedManagerForMatrixSession : _selectedRoomSession ] ;
[ roomDataSourceManager roomDataSourceForRoom : _selectedRoomId create : YES onComplete : ^ ( MXKRoomDataSource * roomDataSource ) {
onComplete ( roomDataSource ) ;
} ] ;
}
else
{
// Open the room on the requested event
[ RoomDataSource loadRoomDataSourceWithRoomId : _selectedRoomId initialEventId : _selectedEventId andMatrixSession : _selectedRoomSession onComplete : ^ ( id roomDataSource ) {
( ( RoomDataSource * ) roomDataSource ) . markTimelineInitialEvent = YES ;
// Give the data source ownership to the room view controller .
self . currentRoomViewController . hasRoomDataSourceOwnership = YES ;
onComplete ( roomDataSource ) ;
} ] ;
}
}
else
{
// Search result : Create a temp timeline from the selected event
[ RoomDataSource loadRoomDataSourceWithRoomId : selectedSearchEvent . roomId initialEventId : selectedSearchEvent . eventId andMatrixSession : selectedSearchEventSession onComplete : ^ ( id roomDataSource ) {
[ roomDataSource finalizeInitialization ] ;
( ( RoomDataSource * ) roomDataSource ) . markTimelineInitialEvent = YES ;
// Give the data source ownership to the room view controller .
self . currentRoomViewController . hasRoomDataSourceOwnership = YES ;
onComplete ( roomDataSource ) ;
} ] ;
}
}
2018-07-23 16:06:53 +00:00
- ( void ) setupLeftBarButtonItem
{
if ( self . splitViewController )
{
// Refresh selected cell without scrolling the selected cell ( We suppose it ' s visible here )
[ self refreshCurrentSelectedCell : NO ] ;
if ( _currentRoomViewController )
{
_currentRoomViewController . navigationItem . leftBarButtonItem = self . splitViewController . displayModeButtonItem ;
_currentRoomViewController . navigationItem . leftItemsSupplementBackButton = YES ;
}
else if ( _currentContactDetailViewController )
{
_currentContactDetailViewController . navigationItem . leftBarButtonItem = self . splitViewController . displayModeButtonItem ;
_currentContactDetailViewController . navigationItem . leftItemsSupplementBackButton = YES ;
}
else if ( _currentGroupDetailViewController )
{
_currentGroupDetailViewController . navigationItem . leftBarButtonItem = self . splitViewController . displayModeButtonItem ;
_currentGroupDetailViewController . navigationItem . leftItemsSupplementBackButton = YES ;
}
}
}
2017-07-21 09:28:17 +00:00
- ( void ) presentViewController : ( UIViewController * ) viewControllerToPresent animated : ( BOOL ) flag completion : ( void ( ^ ) ( void ) ) completion
{
// Keep ref on presented view controller
[ childViewControllers addObject : viewControllerToPresent ] ;
[ super presentViewController : viewControllerToPresent animated : flag completion : completion ] ;
}
2017-03-27 13:59:51 +00:00
// Made the actual selected view controller update its selected cell .
- ( void ) refreshCurrentSelectedCell : ( BOOL ) forceVisible
{
UIViewController * selectedViewController = self . selectedViewController ;
if ( [ selectedViewController respondsToSelector : @ selector ( refreshCurrentSelectedCell : ) ] )
{
[ ( id ) selectedViewController refreshCurrentSelectedCell : forceVisible ] ;
2017-04-27 10:37:29 +00:00
}
}
2017-12-22 13:33:40 +00:00
- ( void ) releaseCurrentDetailsViewController
{
// Release the existing details view controller ( if any ) .
if ( _currentRoomViewController )
{
// If the displayed data is not a preview , let the manager release the room data source
// ( except if the view controller has the room data source ownership ) .
if ( ! _currentRoomViewController . roomPreviewData && _currentRoomViewController . roomDataSource && ! _currentRoomViewController . hasRoomDataSourceOwnership )
{
MXSession * mxSession = _currentRoomViewController . roomDataSource . mxSession ;
MXKRoomDataSourceManager * roomDataSourceManager = [ MXKRoomDataSourceManager sharedManagerForMatrixSession : mxSession ] ;
// Let the manager release live room data sources where the user is in
2018-08-08 08:33:10 +00:00
[ roomDataSourceManager closeRoomDataSourceWithRoomId : _currentRoomViewController . roomDataSource . roomId forceClose : NO ] ;
2017-12-22 13:33:40 +00:00
}
[ _currentRoomViewController destroy ] ;
_currentRoomViewController = nil ;
}
else if ( _currentContactDetailViewController )
{
[ _currentContactDetailViewController destroy ] ;
_currentContactDetailViewController = nil ;
}
else if ( _currentGroupDetailViewController )
{
[ _currentGroupDetailViewController destroy ] ;
_currentGroupDetailViewController = nil ;
}
}
2017-04-27 10:37:29 +00:00
- ( void ) setHidden : ( BOOL ) hidden
{
_hidden = hidden ;
2019-01-11 10:45:27 +00:00
[ self . view superview ] . backgroundColor = ThemeService . shared . theme . backgroundColor ;
2017-04-27 10:37:29 +00:00
self . view . hidden = hidden ;
self . navigationController . navigationBar . hidden = hidden ;
}
2017-03-27 13:59:51 +00:00
2017-04-14 15:01:44 +00:00
# pragma mark -
2017-04-28 12:06:58 +00:00
- ( void ) refreshTabBarBadges
{
2017-06-14 08:06:36 +00:00
// Use a middle dot to signal missed notif in favourites
2018-11-30 15:36:34 +00:00
[ self setMissedDiscussionsMark : ( recentsDataSource . missedFavouriteDiscussionsCount ? @ "\u00B7" : nil )
onTabBarItem : TABBAR_FAVOURITES _INDEX
2019-02-12 18:06:22 +00:00
withBadgeColor : ( recentsDataSource . missedHighlightFavouriteDiscussionsCount ? ThemeService . shared . theme . noticeColor : ThemeService . shared . theme . noticeSecondaryColor ) ] ;
2017-06-14 08:06:36 +00:00
// Update the badge on People and Rooms tabs
2018-11-30 15:36:34 +00:00
[ self setMissedDiscussionsCount : recentsDataSource . missedDirectDiscussionsCount
onTabBarItem : TABBAR_PEOPLE _INDEX
2019-02-12 18:06:22 +00:00
withBadgeColor : ( recentsDataSource . missedHighlightDirectDiscussionsCount ? ThemeService . shared . theme . noticeColor : ThemeService . shared . theme . noticeSecondaryColor ) ] ;
2018-11-30 15:36:34 +00:00
[ self setMissedDiscussionsCount : recentsDataSource . missedGroupDiscussionsCount
onTabBarItem : TABBAR_ROOMS _INDEX
2019-02-12 18:06:22 +00:00
withBadgeColor : ( recentsDataSource . missedHighlightGroupDiscussionsCount ? ThemeService . shared . theme . noticeColor : ThemeService . shared . theme . noticeSecondaryColor ) ] ;
2017-04-28 12:06:58 +00:00
}
- ( void ) setMissedDiscussionsCount : ( NSUInteger ) count onTabBarItem : ( NSUInteger ) index withBadgeColor : ( UIColor * ) badgeColor
2017-04-14 15:01:44 +00:00
{
if ( count )
{
2017-04-28 12:06:58 +00:00
NSString * badgeValue = [ self tabBarBadgeStringValue : count ] ;
2017-04-14 15:01:44 +00:00
2017-04-28 12:06:58 +00:00
self . tabBar . items [ index ] . badgeValue = badgeValue ;
2017-04-18 13:55:51 +00:00
2019-04-25 09:53:38 +00:00
self . tabBar . items [ index ] . badgeColor = badgeColor ;
[ self . tabBar . items [ index ] setBadgeTextAttributes : @ {
NSForegroundColorAttributeName : ThemeService . shared . theme . baseTextPrimaryColor
}
forState : UIControlStateNormal ] ;
2017-04-14 15:01:44 +00:00
}
else
{
2017-04-28 12:06:58 +00:00
self . tabBar . items [ index ] . badgeValue = nil ;
}
}
2017-06-14 08:06:36 +00:00
- ( void ) setMissedDiscussionsMark : ( NSString * ) mark onTabBarItem : ( NSUInteger ) index withBadgeColor : ( UIColor * ) badgeColor
{
if ( mark )
{
self . tabBar . items [ index ] . badgeValue = mark ;
2019-04-25 09:53:38 +00:00
self . tabBar . items [ index ] . badgeColor = badgeColor ;
2017-06-14 08:06:36 +00:00
2019-04-25 09:53:38 +00:00
[ self . tabBar . items [ index ] setBadgeTextAttributes : @ {
NSForegroundColorAttributeName : ThemeService . shared . theme . baseTextPrimaryColor
}
forState : UIControlStateNormal ] ;
2017-06-14 08:06:36 +00:00
}
else
{
self . tabBar . items [ index ] . badgeValue = nil ;
}
}
2017-04-28 12:06:58 +00:00
- ( NSString * ) tabBarBadgeStringValue : ( NSUInteger ) count
{
NSString * badgeValue ;
if ( count > 1000 )
{
CGFloat value = count / 1000.0 ;
badgeValue = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "large_badge_value_k_format" , @ "Vector" , nil ) , value ] ;
}
else
{
badgeValue = [ NSString stringWithFormat : @ "%tu" , count ] ;
2017-04-14 15:01:44 +00:00
}
2017-04-28 12:06:58 +00:00
return badgeValue ;
2017-04-14 15:01:44 +00:00
}
2017-04-28 12:06:58 +00:00
# pragma mark -
2017-03-23 16:48:05 +00:00
2018-06-27 08:43:22 +00:00
- ( void ) promptUserBeforeUsingAnalytics
2017-03-23 16:48:05 +00:00
{
NSLog ( @ "[MasterTabBarController]: Invite the user to send crash reports" ) ;
__weak typeof ( self ) weakSelf = self ;
2017-07-14 14:41:25 +00:00
[ currentAlert dismissViewControllerAnimated : NO completion : nil ] ;
2017-03-23 16:48:05 +00:00
2019-01-07 23:24:11 +00:00
NSString * appDisplayName = [ [ NSBundle mainBundle ] infoDictionary ] [ @ "CFBundleDisplayName" ] ;
2017-03-23 16:48:05 +00:00
2017-07-14 14:41:25 +00:00
currentAlert = [ UIAlertController alertControllerWithTitle : [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "google_analytics_use_prompt" , @ "Vector" , nil ) , appDisplayName ] message : nil preferredStyle : UIAlertControllerStyleAlert ] ;
[ currentAlert addAction : [ UIAlertAction actionWithTitle : [ NSBundle mxk_localizedStringForKey : @ "no" ]
style : UIAlertActionStyleDefault
handler : ^ ( UIAlertAction * action ) {
2018-07-02 12:51:47 +00:00
RiotSettings . shared . enableCrashReport = NO ;
2017-07-14 14:41:25 +00:00
if ( weakSelf )
{
typeof ( self ) self = weakSelf ;
self -> currentAlert = nil ;
}
} ] ] ;
[ currentAlert addAction : [ UIAlertAction actionWithTitle : [ NSBundle mxk_localizedStringForKey : @ "yes" ]
style : UIAlertActionStyleDefault
handler : ^ ( UIAlertAction * action ) {
2018-07-02 12:51:47 +00:00
RiotSettings . shared . enableCrashReport = YES ;
2017-07-14 14:41:25 +00:00
if ( weakSelf )
{
typeof ( self ) self = weakSelf ;
self -> currentAlert = nil ;
}
2018-06-27 07:55:06 +00:00
[ [ Analytics sharedInstance ] start ] ;
2017-07-14 14:41:25 +00:00
} ] ] ;
2018-06-27 08:43:22 +00:00
[ currentAlert mxk_setAccessibilityIdentifier : @ "HomeVCUseAnalyticsAlert" ] ;
2017-07-14 14:41:25 +00:00
[ self presentViewController : currentAlert animated : YES completion : nil ] ;
2017-03-23 16:48:05 +00:00
}
2017-06-14 07:41:15 +00:00
# pragma mark - UITabBarDelegate
- ( void ) tabBar : ( UITabBar * ) tabBar didSelectItem : ( UITabBarItem * ) item
{
2017-06-16 14:55:54 +00:00
// Detect multi - tap on the current selected tab .
if ( item . tag = = self . selectedIndex )
2017-06-14 07:41:15 +00:00
{
// Scroll to the next room with missed notifications .
2017-06-16 14:55:54 +00:00
if ( item . tag = = TABBAR_ROOMS _INDEX )
{
[ self . roomsViewController scrollToNextRoomWithMissedNotifications ] ;
}
else if ( item . tag = = TABBAR_PEOPLE _INDEX )
{
[ self . peopleViewController scrollToNextRoomWithMissedNotifications ] ;
}
else if ( item . tag = = TABBAR_FAVOURITES _INDEX )
{
[ self . favouritesViewController scrollToNextRoomWithMissedNotifications ] ;
}
2017-06-14 07:41:15 +00:00
}
}
2017-03-23 16:48:05 +00:00
@ end