2015-11-20 17:14:15 +00:00
/ *
Copyright 2015 OpenMarket Ltd
2017-03-08 15:14:41 +00:00
Copyright 2017 Vector Creations Ltd
2015-11-20 17:14:15 +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 "RecentsDataSource.h"
2017-04-06 12:27:45 +00:00
# import "RecentCellData.h"
2020-04-21 13:26:16 +00:00
# import "SectionHeaderView.h"
# import "DirectorySectionHeaderContainerView.h"
2015-11-20 17:14:15 +00:00
2019-01-11 09:32:56 +00:00
# import "ThemeService.h"
2015-12-04 16:45:56 +00:00
2017-03-09 10:50:12 +00:00
# import "MXRoom+Riot.h"
2020-06-25 14:01:32 +00:00
# import "MXSession+Riot.h"
2015-12-21 09:35:48 +00:00
2018-07-02 12:51:47 +00:00
# import "Riot-Swift.h"
2016-04-12 07:20:38 +00:00
# define RECENTSDATASOURCE_SECTION _DIRECTORY 0 x01
# define RECENTSDATASOURCE_SECTION _INVITES 0 x02
# define RECENTSDATASOURCE_SECTION _FAVORITES 0 x04
# define RECENTSDATASOURCE_SECTION _CONVERSATIONS 0 x08
# define RECENTSDATASOURCE_SECTION _LOWPRIORITY 0 x10
2018-08-23 14:50:14 +00:00
# define RECENTSDATASOURCE_SECTION _SERVERNOTICE 0 x20
# define RECENTSDATASOURCE_SECTION _PEOPLE 0 x40
2016-04-12 07:20:38 +00:00
2017-04-20 16:06:49 +00:00
# define RECENTSDATASOURCE_DEFAULT _SECTION _HEADER _HEIGHT 30.0
# define RECENTSDATASOURCE_DIRECTORY _SECTION _HEADER _HEIGHT 65.0
NSString * const kRecentsDataSourceTapOnDirectoryServerChange = @ "kRecentsDataSourceTapOnDirectoryServerChange" ;
2020-06-30 19:46:10 +00:00
@ interface RecentsDataSource ( ) < SecureBackupBannerCellDelegate , CrossSigningSetupBannerCellDelegate >
2015-12-02 16:18:55 +00:00
{
2015-12-09 15:09:46 +00:00
NSMutableArray * invitesCellDataArray ;
2015-12-04 08:02:02 +00:00
NSMutableArray * favoriteCellDataArray ;
2017-05-11 09:51:42 +00:00
NSMutableArray * peopleCellDataArray ;
2015-12-04 08:02:02 +00:00
NSMutableArray * conversationCellDataArray ;
NSMutableArray * lowPriorityCellDataArray ;
2018-08-23 14:50:14 +00:00
NSMutableArray * serverNoticeCellDataArray ;
2015-12-02 16:18:55 +00:00
2016-04-12 07:20:38 +00:00
NSInteger shrinkedSectionsBitMask ;
2017-04-20 16:06:49 +00:00
2020-04-21 13:26:16 +00:00
DirectorySectionHeaderContainerView * directorySectionContainer ;
2017-08-14 18:30:16 +00:00
UILabel * networkLabel ;
2017-04-20 16:06:49 +00:00
UILabel * directoryServerLabel ;
2015-12-02 16:18:55 +00:00
NSMutableDictionary < NSString * , id > * roomTagsListenerByUserId ;
2016-06-14 20:25:10 +00:00
2017-03-29 08:37:53 +00:00
// Timer to not refresh publicRoomsDirectoryDataSource on every keystroke .
NSTimer * publicRoomsTriggerTimer ;
2015-12-02 16:18:55 +00:00
}
2019-01-31 18:52:32 +00:00
2020-06-25 15:52:36 +00:00
@ property ( nonatomic , assign , readwrite ) SecureBackupBannerDisplay secureBackupBannerDisplay ;
2020-06-30 19:46:10 +00:00
@ property ( nonatomic , assign , readwrite ) CrossSigningBannerDisplay crossSigningBannerDisplay ;
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
@ property ( nonatomic , strong ) CrossSigningService * crossSigningService ;
2019-01-31 18:52:32 +00:00
2015-12-02 16:18:55 +00:00
@ end
2015-11-20 17:14:15 +00:00
@ implementation RecentsDataSource
2020-06-30 19:46:10 +00:00
@ synthesize directorySection , invitesSection , favoritesSection , peopleSection , conversationSection , lowPrioritySection , serverNoticeSection , secureBackupBannerSection , crossSigningBannerSection ;
2015-12-16 07:59:40 +00:00
@ synthesize hiddenCellIndexPath , droppingCellIndexPath , droppingCellBackGroundView ;
2018-08-23 14:50:14 +00:00
@ synthesize invitesCellDataArray , favoriteCellDataArray , peopleCellDataArray , conversationCellDataArray , lowPriorityCellDataArray , serverNoticeCellDataArray ;
2015-11-20 17:14:15 +00:00
- ( instancetype ) init
{
self = [ super init ] ;
if ( self )
{
2017-04-06 12:27:45 +00:00
invitesCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2015-12-04 08:02:02 +00:00
favoriteCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2017-05-11 09:51:42 +00:00
peopleCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2015-12-04 08:02:02 +00:00
lowPriorityCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2018-08-23 14:50:14 +00:00
serverNoticeCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2017-04-06 12:27:45 +00:00
conversationCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
_crossSigningBannerDisplay = CrossSigningBannerDisplayNone ;
crossSigningBannerSection = -1 ;
2019-01-31 18:52:32 +00:00
2020-06-25 15:52:36 +00:00
_secureBackupBannerDisplay = SecureBackupBannerDisplayNone ;
secureBackupBannerSection = -1 ;
2015-12-16 15:29:34 +00:00
directorySection = -1 ;
2015-12-09 15:09:46 +00:00
invitesSection = -1 ;
2015-12-04 08:02:02 +00:00
favoritesSection = -1 ;
2017-05-11 09:51:42 +00:00
peopleSection = -1 ;
2015-12-04 08:02:02 +00:00
conversationSection = -1 ;
lowPrioritySection = -1 ;
2018-08-23 14:50:14 +00:00
serverNoticeSection = -1 ;
2015-12-02 16:18:55 +00:00
2017-04-06 12:27:45 +00:00
_areSectionsShrinkable = NO ;
2016-04-12 07:20:38 +00:00
shrinkedSectionsBitMask = 0 ;
2015-12-02 16:18:55 +00:00
roomTagsListenerByUserId = [ [ NSMutableDictionary alloc ] init ] ;
2015-12-21 09:35:48 +00:00
2020-06-30 19:46:10 +00:00
_crossSigningService = [ CrossSigningService new ] ;
2020-06-30 15:31:44 +00:00
2015-12-21 09:35:48 +00:00
// Set default data and view classes
[ self registerCellDataClass : RecentCellData . class forCellIdentifier : kMXKRecentCellIdentifier ] ;
2015-11-20 17:14:15 +00:00
}
return self ;
}
2017-04-06 12:27:45 +00:00
# pragma mark -
- ( void ) setDelegate : ( id < MXKDataSourceDelegate > ) delegate andRecentsDataSourceMode : ( RecentsDataSourceMode ) recentsDataSourceMode
{
2017-06-16 13:18:33 +00:00
// Update the configuration , the recentsDataSourceMode setter will force a refresh .
self . delegate = delegate ;
self . recentsDataSourceMode = recentsDataSourceMode ;
2017-04-06 12:27:45 +00:00
}
- ( void ) setRecentsDataSourceMode : ( RecentsDataSourceMode ) recentsDataSourceMode
{
_recentsDataSourceMode = recentsDataSourceMode ;
2019-01-31 18:52:32 +00:00
// Register to key backup state changes only on in home mode .
if ( recentsDataSourceMode = = RecentsDataSourceModeHome )
{
[ self registerKeyBackupStateDidChangeNotification ] ;
}
else
{
[ self unregisterKeyBackupStateDidChangeNotification ] ;
}
2019-02-19 13:51:47 +00:00
2020-06-26 11:07:53 +00:00
[ self updateSecureBackupBanner ] ;
2017-04-06 12:27:45 +00:00
[ self forceRefresh ] ;
2020-06-30 19:46:10 +00:00
[ self refreshCrossSigningBannerDisplay ] ;
2017-04-06 12:27:45 +00:00
}
2017-04-14 09:49:14 +00:00
- ( UIView * ) viewForStickyHeaderInSection : ( NSInteger ) section withFrame : ( CGRect ) frame
{
2017-04-20 16:06:49 +00:00
UIView * stickyHeader ;
2017-04-14 09:49:14 +00:00
2017-04-20 16:06:49 +00:00
NSInteger savedShrinkedSectionsBitMask = shrinkedSectionsBitMask ;
if ( section = = directorySection )
{
// Return the section header used when the section is shrinked
shrinkedSectionsBitMask = RECENTSDATASOURCE_SECTION _DIRECTORY ;
}
stickyHeader = [ self viewForHeaderInSection : section withFrame : frame ] ;
shrinkedSectionsBitMask = savedShrinkedSectionsBitMask ;
return stickyHeader ;
}
2017-04-21 06:37:58 +00:00
2019-01-31 18:52:32 +00:00
# pragma mark - Key backup setup banner
- ( void ) registerKeyBackupStateDidChangeNotification
{
2019-02-06 16:34:16 +00:00
// Check homeserver update in background
[ self . mxSession . crypto . backup forceRefresh : nil failure : nil ] ;
2019-01-31 18:52:32 +00:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( keyBackupStateDidChangeNotification : ) name : kMXKeyBackupDidStateChangeNotification object : nil ] ;
}
- ( void ) unregisterKeyBackupStateDidChangeNotification
{
[ [ NSNotificationCenter defaultCenter ] removeObserver : self name : kMXKeyBackupDidStateChangeNotification object : nil ] ;
}
- ( void ) keyBackupStateDidChangeNotification : ( NSNotification * ) notification
{
2020-06-26 11:07:53 +00:00
if ( [ self updateSecureBackupBanner ] )
2019-02-18 17:25:50 +00:00
{
[ self forceRefresh ] ;
}
2019-01-31 18:52:32 +00:00
}
2020-06-26 11:07:53 +00:00
- ( BOOL ) updateSecureBackupBanner
2019-01-31 18:52:32 +00:00
{
2020-06-26 11:07:53 +00:00
SecureBackupBannerDisplay secureBackupBanner = SecureBackupBannerDisplayNone ;
2020-06-25 14:01:32 +00:00
if ( self . recentsDataSourceMode = = RecentsDataSourceModeHome )
2019-01-31 18:52:32 +00:00
{
2020-06-26 11:07:53 +00:00
SecureBackupBannerPreferences * secureBackupBannersPreferences = SecureBackupBannerPreferences . shared ;
2019-01-31 18:52:32 +00:00
2020-10-01 14:42:24 +00:00
// Display the banner if only we can set up 4 S and if there are messages keys to backup
if ( ! secureBackupBannersPreferences . hideSetupBanner
&& [ self . mxSession vc_canSetupSecureBackup ]
&& self . mxSession . crypto . backup . hasKeysToBackup )
2020-06-25 14:01:32 +00:00
{
2020-06-26 11:07:53 +00:00
secureBackupBanner = SecureBackupBannerDisplaySetup ;
2019-01-31 18:52:32 +00:00
}
}
2020-06-25 14:01:32 +00:00
2020-06-26 11:07:53 +00:00
BOOL updated = ( self . secureBackupBannerDisplay ! = secureBackupBanner ) ;
2020-06-25 14:01:32 +00:00
2020-06-26 11:07:53 +00:00
self . secureBackupBannerDisplay = secureBackupBanner ;
2020-06-25 14:01:32 +00:00
2019-02-18 17:25:50 +00:00
return updated ;
2019-01-31 18:52:32 +00:00
}
2020-06-26 12:11:58 +00:00
- ( void ) hideKeyBackupBannerWithDisplay : ( SecureBackupBannerDisplay ) secureBackupBannerDisplay
2019-01-31 18:52:32 +00:00
{
2020-06-26 11:07:53 +00:00
SecureBackupBannerPreferences * keyBackupBannersPreferences = SecureBackupBannerPreferences . shared ;
2019-01-31 18:52:32 +00:00
2020-06-26 12:11:58 +00:00
switch ( secureBackupBannerDisplay ) {
2020-06-25 15:52:36 +00:00
case SecureBackupBannerDisplaySetup :
2019-01-31 18:52:32 +00:00
keyBackupBannersPreferences . hideSetupBanner = YES ;
break ;
default :
break ;
}
2020-06-26 11:07:53 +00:00
[ self updateSecureBackupBanner ] ;
2019-01-31 18:52:32 +00:00
[ self forceRefresh ] ;
}
2020-06-30 19:46:10 +00:00
# pragma mark - Cross - signing setup banner
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
- ( void ) refreshCrossSigningBannerDisplay
2020-06-30 15:31:44 +00:00
{
if ( self . recentsDataSourceMode = = RecentsDataSourceModeHome )
{
2020-06-30 19:46:10 +00:00
CrossSigningBannerPreferences * crossSigningBannerPreferences = CrossSigningBannerPreferences . shared ;
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
if ( ! crossSigningBannerPreferences . hideSetupBanner )
2020-06-30 15:31:44 +00:00
{
2020-06-30 19:46:10 +00:00
[ self . crossSigningService canSetupCrossSigningFor : self . mxSession success : ^ ( BOOL canSetupCrossSigning ) {
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
CrossSigningBannerDisplay crossSigningBannerDisplay = canSetupCrossSigning ? CrossSigningBannerDisplaySetup : CrossSigningBannerDisplayNone ;
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
[ self updateCrossSigningBannerDisplay : crossSigningBannerDisplay ] ;
2020-06-30 15:31:44 +00:00
} failure : ^ ( NSError * _Nonnull error ) {
2020-06-30 19:46:10 +00:00
NSLog ( @ "[RecentsDataSource] refreshCrossSigningBannerDisplay: Fail to verify if cross signing banner can be displayed" ) ;
2020-06-30 15:31:44 +00:00
} ] ;
}
else
{
2020-06-30 19:46:10 +00:00
[ self updateCrossSigningBannerDisplay : CrossSigningBannerDisplayNone ] ;
2020-06-30 15:31:44 +00:00
}
}
else
{
2020-06-30 19:46:10 +00:00
[ self updateCrossSigningBannerDisplay : CrossSigningBannerDisplayNone ] ;
2020-06-30 15:31:44 +00:00
}
}
2020-06-30 19:46:10 +00:00
- ( void ) updateCrossSigningBannerDisplay : ( CrossSigningBannerDisplay ) crossSigningBannerDisplay
2020-06-30 15:31:44 +00:00
{
2020-06-30 19:46:10 +00:00
if ( self . crossSigningBannerDisplay = = crossSigningBannerDisplay )
2020-06-30 15:31:44 +00:00
{
return ;
}
2020-06-30 19:46:10 +00:00
self . crossSigningBannerDisplay = crossSigningBannerDisplay ;
2020-06-30 15:31:44 +00:00
[ self forceRefresh ] ;
}
2020-06-30 19:46:10 +00:00
- ( void ) hideCrossSigningBannerWithDisplay : ( CrossSigningBannerDisplay ) crossSigningBannerDisplay
2020-06-30 15:31:44 +00:00
{
2020-06-30 19:46:10 +00:00
CrossSigningBannerPreferences * crossSigningBannerPreferences = CrossSigningBannerPreferences . shared ;
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
switch ( crossSigningBannerDisplay ) {
case CrossSigningBannerDisplaySetup :
crossSigningBannerPreferences . hideSetupBanner = YES ;
2020-06-30 15:31:44 +00:00
break ;
default :
break ;
}
2020-06-30 19:46:10 +00:00
[ self refreshCrossSigningBannerDisplay ] ;
2020-06-30 15:31:44 +00:00
}
2017-04-06 12:27:45 +00:00
# pragma mark -
2015-12-18 09:59:45 +00:00
2016-03-10 17:00:40 +00:00
- ( MXKSessionRecentsDataSource * ) addMatrixSession : ( MXSession * ) mxSession
2015-12-18 09:59:45 +00:00
{
2016-03-10 17:00:40 +00:00
MXKSessionRecentsDataSource * recentsDataSource = [ super addMatrixSession : mxSession ] ;
2015-12-18 09:59:45 +00:00
// Initialise the public room directory data source
// Note that it is single matrix session only for now
2015-12-18 16:17:03 +00:00
if ( ! _publicRoomsDirectoryDataSource )
2015-12-18 09:59:45 +00:00
{
2015-12-18 16:17:03 +00:00
_publicRoomsDirectoryDataSource = [ [ PublicRoomsDirectoryDataSource alloc ] initWithMatrixSession : mxSession ] ;
2021-03-03 15:33:11 +00:00
_publicRoomsDirectoryDataSource . showNSFWRooms = RiotSettings . shared . showNSFWPublicRooms ;
2015-12-18 16:17:03 +00:00
_publicRoomsDirectoryDataSource . delegate = self ;
2015-12-18 09:59:45 +00:00
}
2016-03-10 17:00:40 +00:00
return recentsDataSource ;
2015-12-18 09:59:45 +00:00
}
2015-12-02 16:18:55 +00:00
- ( void ) removeMatrixSession : ( MXSession * ) matrixSession
{
[ super removeMatrixSession : matrixSession ] ;
// sanity check
2016-06-21 20:06:32 +00:00
if ( matrixSession . myUser && matrixSession . myUser . userId )
2015-12-02 16:18:55 +00:00
{
2019-01-07 23:24:11 +00:00
id roomTagListener = roomTagsListenerByUserId [ matrixSession . myUser . userId ] ;
2015-12-02 16:18:55 +00:00
if ( roomTagListener )
{
2016-03-10 17:00:40 +00:00
[ matrixSession removeListener : roomTagListener ] ;
2015-12-02 16:18:55 +00:00
[ roomTagsListenerByUserId removeObjectForKey : matrixSession . myUser . userId ] ;
}
2016-06-21 20:06:32 +00:00
}
if ( _publicRoomsDirectoryDataSource . mxSession = = matrixSession )
{
[ _publicRoomsDirectoryDataSource destroy ] ;
_publicRoomsDirectoryDataSource = nil ;
2015-12-02 16:18:55 +00:00
}
}
- ( void ) dataSource : ( MXKDataSource * ) dataSource didStateChange : ( MXKDataSourceState ) aState
{
2015-12-18 16:17:03 +00:00
if ( dataSource = = _publicRoomsDirectoryDataSource )
2015-12-18 09:59:45 +00:00
{
2017-04-07 13:44:29 +00:00
if ( -1 ! = directorySection && ! self . droppingCellIndexPath )
2017-04-07 12:09:15 +00:00
{
// TODO : We should only update the directory section
[ self . delegate dataSource : self didCellChange : nil ] ;
}
2015-12-18 09:59:45 +00:00
}
else
{
[ super dataSource : dataSource didStateChange : aState ] ;
2016-03-10 17:00:40 +00:00
if ( ( aState = = MXKDataSourceStateReady ) && dataSource . mxSession . myUser . userId )
2015-12-18 09:59:45 +00:00
{
// Register the room tags updates to refresh the favorites order
2016-03-10 17:00:40 +00:00
id roomTagsListener = [ dataSource . mxSession listenToEventsOfTypes : @ [ kMXEventTypeStringRoomTag ]
2016-02-26 16:08:53 +00:00
onEvent : ^ ( MXEvent * event , MXTimelineDirection direction , id customObject ) {
2015-12-18 09:59:45 +00:00
// Consider only live event
2016-02-26 16:08:53 +00:00
if ( direction = = MXTimelineDirectionForwards )
2015-12-18 09:59:45 +00:00
{
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2017-04-06 12:27:45 +00:00
[ self forceRefresh ] ;
2015-12-18 09:59:45 +00:00
} ) ;
}
} ] ;
2019-01-07 23:24:11 +00:00
roomTagsListenerByUserId [ dataSource . mxSession . myUser . userId ] = roomTagsListener ;
2015-12-18 09:59:45 +00:00
}
2015-12-02 16:18:55 +00:00
}
2015-12-10 09:16:22 +00:00
}
2017-04-06 12:27:45 +00:00
- ( void ) forceRefresh
2015-12-10 09:16:22 +00:00
{
2015-12-16 07:59:40 +00:00
// Refresh is disabled during drag & drop animation "
if ( ! self . droppingCellIndexPath )
2015-12-10 09:16:22 +00:00
{
2015-12-14 07:29:01 +00:00
[ self refreshRoomsSections ] ;
// And inform the delegate about the update
2015-12-10 09:16:22 +00:00
[ self . delegate dataSource : self didCellChange : nil ] ;
}
2015-12-02 16:18:55 +00:00
}
2015-12-10 09:16:22 +00:00
- ( void ) didMXSessionInviteRoomUpdate : ( NSNotification * ) notif
{
MXSession * mxSession = notif . object ;
2016-03-10 17:00:40 +00:00
if ( [ self . mxSessions indexOfObject : mxSession ] ! = NSNotFound )
2015-12-10 09:16:22 +00:00
{
2017-04-06 12:27:45 +00:00
[ self forceRefresh ] ;
2016-05-30 11:42:45 +00:00
}
}
2015-12-02 16:18:55 +00:00
# pragma mark - UITableViewDataSource
- ( NSInteger ) numberOfSectionsInTableView : ( UITableView * ) tableView
{
2017-05-19 15:22:26 +00:00
// Sanity check
if ( tableView . tag ! = self . recentsDataSourceMode )
{
// The view controller of this table view is not the current selected one in the tab bar controller .
return 0 ;
}
2017-04-11 15:58:59 +00:00
NSInteger sectionsCount = 0 ;
2015-12-02 16:18:55 +00:00
// Check whether all data sources are ready before rendering recents
if ( self . state = = MXKDataSourceStateReady )
{
2020-06-30 19:46:10 +00:00
crossSigningBannerSection = secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = invitesSection = serverNoticeSection = -1 ;
2019-01-31 18:52:32 +00:00
2020-06-30 19:46:10 +00:00
if ( self . crossSigningBannerDisplay ! = CrossSigningBannerDisplayNone )
2020-06-30 15:31:44 +00:00
{
2020-06-30 19:46:10 +00:00
crossSigningBannerSection = sectionsCount + + ;
2020-06-30 15:31:44 +00:00
}
else if ( self . secureBackupBannerDisplay ! = SecureBackupBannerDisplayNone )
2019-01-31 18:52:32 +00:00
{
2020-06-30 15:31:44 +00:00
secureBackupBannerSection = sectionsCount + + ;
2019-01-31 18:52:32 +00:00
}
2017-04-11 15:58:59 +00:00
if ( invitesCellDataArray . count > 0 )
{
invitesSection = sectionsCount + + ;
}
if ( favoriteCellDataArray . count > 0 )
{
favoritesSection = sectionsCount + + ;
}
2017-05-12 15:39:05 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModeHome )
2017-05-11 09:51:42 +00:00
{
peopleSection = sectionsCount + + ;
}
2017-05-05 13:30:35 +00:00
// Keep visible the main rooms section even if it is empty , except on favourites screen .
if ( _recentsDataSourceMode ! = RecentsDataSourceModeFavourites )
2017-04-11 15:58:59 +00:00
{
conversationSection = sectionsCount + + ;
}
2020-07-31 13:14:26 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModeRooms
2020-08-03 13:07:39 +00:00
&& BuildSettings . publicRoomsShowDirectory )
2017-04-11 15:58:59 +00:00
{
// Add the directory section after "ROOMS"
directorySection = sectionsCount + + ;
}
if ( lowPriorityCellDataArray . count > 0 )
{
lowPrioritySection = sectionsCount + + ;
}
2018-08-23 14:50:14 +00:00
if ( serverNoticeCellDataArray . count > 0 )
{
serverNoticeSection = sectionsCount + + ;
}
2015-12-02 16:18:55 +00:00
}
2017-04-11 15:58:59 +00:00
return sectionsCount ;
2015-12-02 16:18:55 +00:00
}
- ( NSInteger ) tableView : ( UITableView * ) tableView numberOfRowsInSection : ( NSInteger ) section
{
2017-05-19 15:22:26 +00:00
// Sanity check
if ( tableView . tag ! = self . recentsDataSourceMode )
{
// The view controller of this table view is not the current selected one in the tab bar controller .
return 0 ;
}
2015-12-02 16:18:55 +00:00
NSUInteger count = 0 ;
2017-04-07 12:09:15 +00:00
2020-06-30 19:46:10 +00:00
if ( section = = self . crossSigningBannerSection && self . crossSigningBannerDisplay ! = CrossSigningBannerDisplayNone )
2020-06-30 15:31:44 +00:00
{
count = 1 ;
}
else if ( section = = self . secureBackupBannerSection && self . secureBackupBannerDisplay ! = SecureBackupBannerDisplayNone )
2019-01-31 18:52:32 +00:00
{
count = 1 ;
}
else if ( section = = favoritesSection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _FAVORITES ) )
2015-12-02 16:18:55 +00:00
{
2015-12-04 08:02:02 +00:00
count = favoriteCellDataArray . count ;
2015-12-02 16:18:55 +00:00
}
2017-05-11 09:51:42 +00:00
else if ( section = = peopleSection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _PEOPLE ) )
{
count = peopleCellDataArray . count ? peopleCellDataArray . count : 1 ;
}
2016-04-12 07:20:38 +00:00
else if ( section = = conversationSection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _CONVERSATIONS ) )
2015-12-02 16:18:55 +00:00
{
2017-04-26 09:10:44 +00:00
count = conversationCellDataArray . count ? conversationCellDataArray . count : 1 ;
2015-12-02 16:18:55 +00:00
}
2017-04-07 12:09:15 +00:00
else if ( section = = directorySection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _DIRECTORY ) )
{
2017-04-07 13:44:29 +00:00
count = [ _publicRoomsDirectoryDataSource tableView : tableView numberOfRowsInSection : 0 ] ;
2017-04-07 12:09:15 +00:00
}
2016-04-12 07:20:38 +00:00
else if ( section = = lowPrioritySection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _LOWPRIORITY ) )
2015-12-02 16:18:55 +00:00
{
2015-12-04 08:02:02 +00:00
count = lowPriorityCellDataArray . count ;
2015-12-02 16:18:55 +00:00
}
2018-08-23 14:50:14 +00:00
else if ( section = = serverNoticeSection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _SERVERNOTICE ) )
{
count = serverNoticeCellDataArray . count ;
}
2016-04-12 07:20:38 +00:00
else if ( section = = invitesSection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _INVITES ) )
2015-12-09 15:09:46 +00:00
{
count = invitesCellDataArray . count ;
}
2017-04-06 12:27:45 +00:00
// Adjust this count according to the potential dragged cell .
2015-12-14 09:47:10 +00:00
if ( [ self isMovingCellSection : section ] )
2015-12-11 13:59:55 +00:00
{
count + + ;
}
2015-12-14 09:47:10 +00:00
2016-04-12 07:20:38 +00:00
if ( count && [ self isHiddenCellSection : section ] )
2015-12-14 09:47:10 +00:00
{
count - - ;
}
2015-12-02 16:18:55 +00:00
return count ;
}
2017-04-20 16:06:49 +00:00
- ( CGFloat ) heightForHeaderInSection : ( NSInteger ) section
{
2020-06-30 19:46:10 +00:00
if ( section = = self . secureBackupBannerSection || section = = self . crossSigningBannerSection )
2019-01-31 18:52:32 +00:00
{
return 0.0 ;
}
2020-07-31 13:14:26 +00:00
else if ( section = = directorySection
&& ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _DIRECTORY )
2020-08-03 13:07:39 +00:00
&& BuildSettings . publicRoomsAllowServerChange )
2017-04-20 16:06:49 +00:00
{
return RECENTSDATASOURCE_DIRECTORY _SECTION _HEADER _HEIGHT ;
}
return RECENTSDATASOURCE_DEFAULT _SECTION _HEADER _HEIGHT ;
}
2017-05-09 08:03:55 +00:00
- ( NSAttributedString * ) attributedStringForHeaderTitleInSection : ( NSInteger ) section
2015-12-02 16:18:55 +00:00
{
2017-05-05 16:11:44 +00:00
NSAttributedString * sectionTitle ;
NSString * title ;
2017-04-11 15:58:59 +00:00
NSUInteger count = 0 ;
2015-12-02 16:18:55 +00:00
2017-04-11 15:58:59 +00:00
if ( section = = favoritesSection )
2015-12-02 16:18:55 +00:00
{
2017-04-11 15:58:59 +00:00
count = favoriteCellDataArray . count ;
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "room_recents_favourites_section" , @ "Vector" , nil ) ;
2017-04-11 15:58:59 +00:00
}
2017-05-11 09:51:42 +00:00
else if ( section = = peopleSection )
{
count = peopleCellDataArray . count ;
title = NSLocalizedStringFromTable ( @ "room_recents_people_section" , @ "Vector" , nil ) ;
}
2017-04-11 15:58:59 +00:00
else if ( section = = conversationSection )
{
count = conversationCellDataArray . count ;
2017-05-05 16:11:44 +00:00
2017-04-11 15:58:59 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModePeople )
2017-04-07 12:09:15 +00:00
{
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "people_conversation_section" , @ "Vector" , nil ) ;
2017-04-07 12:09:15 +00:00
}
2017-04-11 15:58:59 +00:00
else
2015-12-02 16:18:55 +00:00
{
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "room_recents_conversations_section" , @ "Vector" , nil ) ;
2015-12-02 16:18:55 +00:00
}
2017-04-11 15:58:59 +00:00
}
else if ( section = = directorySection )
{
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "room_recents_directory_section" , @ "Vector" , nil ) ;
2017-04-11 15:58:59 +00:00
}
else if ( section = = lowPrioritySection )
{
count = lowPriorityCellDataArray . count ;
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "room_recents_low_priority_section" , @ "Vector" , nil ) ;
2017-04-11 15:58:59 +00:00
}
2018-08-23 14:50:14 +00:00
else if ( section = = serverNoticeSection )
{
count = serverNoticeCellDataArray . count ;
title = NSLocalizedStringFromTable ( @ "room_recents_server_notice_section" , @ "Vector" , nil ) ;
}
2017-04-11 15:58:59 +00:00
else if ( section = = invitesSection )
{
count = invitesCellDataArray . count ;
2015-12-02 16:18:55 +00:00
2017-04-11 15:58:59 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModePeople )
{
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "people_invites_section" , @ "Vector" , nil ) ;
2016-04-12 07:20:38 +00:00
}
2017-04-11 15:58:59 +00:00
else
{
2017-05-05 16:11:44 +00:00
title = NSLocalizedStringFromTable ( @ "room_recents_invites_section" , @ "Vector" , nil ) ;
2017-04-11 15:58:59 +00:00
}
}
2017-05-05 16:11:44 +00:00
if ( count )
{
NSString * roomCount = [ NSString stringWithFormat : @ " %tu" , count ] ;
NSMutableAttributedString * mutableSectionTitle = [ [ NSMutableAttributedString alloc ] initWithString : title
2019-01-11 10:45:27 +00:00
attributes : @ { NSForegroundColorAttributeName : ThemeService . shared . theme . headerTextPrimaryColor ,
2017-05-05 16:11:44 +00:00
NSFontAttributeName : [ UIFont boldSystemFontOfSize : 15.0 ] } ] ;
[ mutableSectionTitle appendAttributedString : [ [ NSMutableAttributedString alloc ] initWithString : roomCount
2019-01-11 10:45:27 +00:00
attributes : @ { NSForegroundColorAttributeName : ThemeService . shared . theme . headerTextSecondaryColor ,
2017-05-05 16:11:44 +00:00
NSFontAttributeName : [ UIFont boldSystemFontOfSize : 15.0 ] } ] ] ;
sectionTitle = mutableSectionTitle ;
}
else if ( title )
{
sectionTitle = [ [ NSAttributedString alloc ] initWithString : title
2019-01-11 10:45:27 +00:00
attributes : @ { NSForegroundColorAttributeName : ThemeService . shared . theme . headerTextPrimaryColor ,
2017-05-05 16:11:44 +00:00
NSFontAttributeName : [ UIFont boldSystemFontOfSize : 15.0 ] } ] ;
}
2017-04-11 15:58:59 +00:00
return sectionTitle ;
}
2017-06-14 11:58:26 +00:00
- ( UIView * ) badgeViewForHeaderTitleInHomeSection : ( NSInteger ) section
{
// Prepare a badge to display the total of missed notifications in this section .
NSUInteger count = 0 ;
NSArray * sectionArray ;
UIView * missedNotifAndUnreadBadgeBgView = nil ;
if ( section = = favoritesSection )
{
sectionArray = favoriteCellDataArray ;
}
else if ( section = = peopleSection )
{
sectionArray = peopleCellDataArray ;
}
else if ( section = = conversationSection )
{
sectionArray = conversationCellDataArray ;
}
else if ( section = = lowPrioritySection )
{
sectionArray = lowPriorityCellDataArray ;
}
2018-08-23 14:50:14 +00:00
else if ( section = = serverNoticeSection )
{
sectionArray = serverNoticeCellDataArray ;
}
2019-02-28 22:09:57 +00:00
BOOL highlight = NO ;
2017-06-14 11:58:26 +00:00
for ( id < MXKRecentCellDataStoring > cellData in sectionArray )
{
count + = cellData . notificationCount ;
2019-02-28 22:09:57 +00:00
highlight | = ( cellData . highlightCount > 0 ) ;
2017-06-14 11:58:26 +00:00
}
if ( count )
{
UILabel * missedNotifAndUnreadBadgeLabel = [ [ UILabel alloc ] init ] ;
2019-02-21 12:07:37 +00:00
missedNotifAndUnreadBadgeLabel . textColor = ThemeService . shared . theme . baseTextPrimaryColor ;
2017-06-14 11:58:26 +00:00
missedNotifAndUnreadBadgeLabel . font = [ UIFont boldSystemFontOfSize : 14 ] ;
if ( count > 1000 )
{
CGFloat value = count / 1000.0 ;
missedNotifAndUnreadBadgeLabel . text = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "large_badge_value_k_format" , @ "Vector" , nil ) , value ] ;
}
else
{
missedNotifAndUnreadBadgeLabel . text = [ NSString stringWithFormat : @ "%tu" , count ] ;
}
[ missedNotifAndUnreadBadgeLabel sizeToFit ] ;
CGFloat bgViewWidth = missedNotifAndUnreadBadgeLabel . frame . size . width + 18 ;
missedNotifAndUnreadBadgeBgView = [ [ UIView alloc ] initWithFrame : CGRectMake ( 0 , 0 , bgViewWidth , 20 ) ] ;
[ missedNotifAndUnreadBadgeBgView . layer setCornerRadius : 10 ] ;
2019-02-28 22:09:57 +00:00
missedNotifAndUnreadBadgeBgView . backgroundColor = highlight ? ThemeService . shared . theme . noticeColor : ThemeService . shared . theme . noticeSecondaryColor ;
2017-06-14 11:58:26 +00:00
[ missedNotifAndUnreadBadgeBgView addSubview : missedNotifAndUnreadBadgeLabel ] ;
missedNotifAndUnreadBadgeLabel . center = missedNotifAndUnreadBadgeBgView . center ;
2020-04-21 13:26:16 +00:00
[ missedNotifAndUnreadBadgeLabel . centerXAnchor constraintEqualToAnchor : missedNotifAndUnreadBadgeBgView . centerXAnchor
constant : 0 ] . active = YES ;
[ missedNotifAndUnreadBadgeLabel . centerYAnchor constraintEqualToAnchor : missedNotifAndUnreadBadgeBgView . centerYAnchor
constant : 0 ] . active = YES ;
2017-06-14 11:58:26 +00:00
}
return missedNotifAndUnreadBadgeBgView ;
}
2017-04-11 15:58:59 +00:00
- ( UIView * ) viewForHeaderInSection : ( NSInteger ) section withFrame : ( CGRect ) frame
{
2019-01-31 18:52:32 +00:00
// No header view in key backup banner section
2020-06-30 19:46:10 +00:00
if ( section = = self . secureBackupBannerSection || section = = self . crossSigningBannerSection )
2019-01-31 18:52:32 +00:00
{
return nil ;
}
2020-04-21 13:26:16 +00:00
SectionHeaderView * sectionHeader = [ [ SectionHeaderView alloc ] initWithFrame : frame ] ;
2019-01-11 10:45:27 +00:00
sectionHeader . backgroundColor = ThemeService . shared . theme . headerBackgroundColor ;
2020-04-21 13:26:16 +00:00
sectionHeader . topViewHeight = RECENTSDATASOURCE_DEFAULT _SECTION _HEADER _HEIGHT ;
2017-04-11 15:58:59 +00:00
NSInteger sectionBitwise = 0 ;
2020-04-21 13:26:16 +00:00
2017-04-11 15:58:59 +00:00
if ( _areSectionsShrinkable )
{
if ( section = = favoritesSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _FAVORITES ;
}
2017-05-11 09:51:42 +00:00
else if ( section = = peopleSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _PEOPLE ;
}
2017-04-11 15:58:59 +00:00
else if ( section = = conversationSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _CONVERSATIONS ;
}
else if ( section = = directorySection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _CONVERSATIONS ;
}
else if ( section = = lowPrioritySection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _LOWPRIORITY ;
}
2018-08-23 14:50:14 +00:00
else if ( section = = serverNoticeSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _SERVERNOTICE ;
}
2017-04-11 15:58:59 +00:00
else if ( section = = invitesSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _INVITES ;
}
}
if ( sectionBitwise )
{
// Add shrink button
UIButton * shrinkButton = [ UIButton buttonWithType : UIButtonTypeCustom ] ;
shrinkButton . backgroundColor = [ UIColor clearColor ] ;
[ shrinkButton addTarget : self action : @ selector ( onButtonPressed : ) forControlEvents : UIControlEventTouchUpInside ] ;
shrinkButton . tag = sectionBitwise ;
[ sectionHeader addSubview : shrinkButton ] ;
2020-04-21 13:26:16 +00:00
sectionHeader . topSpanningView = shrinkButton ;
2017-04-11 15:58:59 +00:00
sectionHeader . userInteractionEnabled = YES ;
2016-04-12 07:20:38 +00:00
2017-04-11 15:58:59 +00:00
// Add shrink icon
UIImage * chevron ;
if ( shrinkedSectionsBitMask & sectionBitwise )
{
chevron = [ UIImage imageNamed : @ "disclosure_icon" ] ;
}
else
{
chevron = [ UIImage imageNamed : @ "shrink_icon" ] ;
}
2020-04-21 13:26:16 +00:00
UIImageView * chevronView = [ [ UIImageView alloc ] initWithImage : chevron ] ;
2020-07-16 21:16:11 +00:00
chevronView . tintColor = ThemeService . shared . theme . textSecondaryColor ;
2017-04-11 15:58:59 +00:00
chevronView . contentMode = UIViewContentModeCenter ;
[ sectionHeader addSubview : chevronView ] ;
2020-04-21 13:26:16 +00:00
sectionHeader . accessoryView = chevronView ;
2017-06-14 11:58:26 +00:00
}
else if ( _recentsDataSourceMode = = RecentsDataSourceModeHome )
{
// Add a badge to display the total of missed notifications by section .
2020-04-21 13:26:16 +00:00
UIView * badgeView = [ self badgeViewForHeaderTitleInHomeSection : section ] ;
2017-06-14 11:58:26 +00:00
2020-04-21 13:26:16 +00:00
if ( badgeView )
2017-06-14 11:58:26 +00:00
{
2020-04-21 13:26:16 +00:00
[ sectionHeader addSubview : badgeView ] ;
sectionHeader . accessoryView = badgeView ;
2017-06-14 11:58:26 +00:00
}
2016-04-12 07:20:38 +00:00
}
2017-04-11 15:58:59 +00:00
// Add label
2017-04-21 08:00:01 +00:00
frame . size . height = RECENTSDATASOURCE_DEFAULT _SECTION _HEADER _HEIGHT - 10 ;
2017-04-11 15:58:59 +00:00
UILabel * headerLabel = [ [ UILabel alloc ] initWithFrame : frame ] ;
headerLabel . backgroundColor = [ UIColor clearColor ] ;
2017-05-09 08:03:55 +00:00
headerLabel . attributedText = [ self attributedStringForHeaderTitleInSection : section ] ;
2017-04-11 15:58:59 +00:00
[ sectionHeader addSubview : headerLabel ] ;
2020-04-21 13:26:16 +00:00
sectionHeader . headerLabel = headerLabel ;
2017-04-20 16:06:49 +00:00
2020-07-31 13:14:26 +00:00
if ( section = = directorySection
&& _recentsDataSourceMode = = RecentsDataSourceModeRooms
&& ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _DIRECTORY )
2020-08-03 13:07:39 +00:00
&& BuildSettings . publicRoomsAllowServerChange )
2017-04-20 16:06:49 +00:00
{
if ( ! directorySectionContainer )
{
2020-04-21 13:26:16 +00:00
directorySectionContainer = [ [ DirectorySectionHeaderContainerView alloc ] initWithFrame : CGRectZero ] ;
2017-04-20 16:06:49 +00:00
directorySectionContainer . backgroundColor = [ UIColor clearColor ] ;
2017-05-04 07:26:02 +00:00
// Add the "Network" label at the left
2020-04-21 13:26:16 +00:00
networkLabel = [ [ UILabel alloc ] initWithFrame : CGRectMake ( 0 , 0 , 100 , 30 ) ] ;
2017-05-04 07:26:02 +00:00
networkLabel . font = [ UIFont systemFontOfSize : 16.0 ] ;
networkLabel . text = NSLocalizedStringFromTable ( @ "room_recents_directory_section_network" , @ "Vector" , nil ) ;
[ directorySectionContainer addSubview : networkLabel ] ;
2020-04-21 13:26:16 +00:00
directorySectionContainer . networkLabel = networkLabel ;
2017-05-04 07:26:02 +00:00
// Add label for selected directory server
2020-04-21 13:26:16 +00:00
directoryServerLabel = [ [ UILabel alloc ] initWithFrame : CGRectMake ( 0 , 0 , 0 , 30 ) ] ;
2017-04-20 16:06:49 +00:00
directoryServerLabel . font = [ UIFont systemFontOfSize : 16.0 ] ;
2017-05-04 07:26:02 +00:00
directoryServerLabel . textAlignment = NSTextAlignmentRight ;
2017-04-20 16:06:49 +00:00
[ directorySectionContainer addSubview : directoryServerLabel ] ;
2020-04-21 13:26:16 +00:00
directorySectionContainer . directoryServerLabel = directoryServerLabel ;
2017-04-20 16:06:49 +00:00
2017-05-04 07:26:02 +00:00
// Chevron
2020-04-21 13:26:16 +00:00
UIImageView * chevronImageView = [ [ UIImageView alloc ] initWithFrame : CGRectMake ( 0 , 0 , 6 , 12 ) ] ;
chevronImageView . contentMode = UIViewContentModeScaleAspectFit ;
2017-04-20 16:06:49 +00:00
chevronImageView . image = [ UIImage imageNamed : @ "disclosure_icon" ] ;
2020-07-16 21:16:11 +00:00
chevronImageView . tintColor = ThemeService . shared . theme . textSecondaryColor ;
2017-04-20 16:06:49 +00:00
[ directorySectionContainer addSubview : chevronImageView ] ;
2020-04-21 13:26:16 +00:00
directorySectionContainer . disclosureView = chevronImageView ;
2017-04-20 16:06:49 +00:00
// Set a tap listener on all the container
UITapGestureRecognizer * tapGesture = [ [ UITapGestureRecognizer alloc ] initWithTarget : self action : @ selector ( onDirectoryServerPickerTap : ) ] ;
[ tapGesture setNumberOfTouchesRequired : 1 ] ;
[ tapGesture setNumberOfTapsRequired : 1 ] ;
[ directorySectionContainer addGestureRecognizer : tapGesture ] ;
}
2017-08-14 18:30:16 +00:00
// Apply the current UI theme .
2019-01-11 10:45:27 +00:00
networkLabel . textColor = ThemeService . shared . theme . textPrimaryColor ;
directoryServerLabel . textColor = ThemeService . shared . theme . textSecondaryColor ;
2017-04-20 16:06:49 +00:00
// Set the current directory server name
directoryServerLabel . text = _publicRoomsDirectoryDataSource . directoryServerDisplayname ;
// Add the check box container
[ sectionHeader addSubview : directorySectionContainer ] ;
2020-04-21 13:26:16 +00:00
sectionHeader . bottomView = directorySectionContainer ;
2017-04-20 16:06:49 +00:00
}
2016-04-12 07:20:38 +00:00
return sectionHeader ;
2015-12-02 16:18:55 +00:00
}
2016-11-30 10:41:20 +00:00
- ( UITableViewCell * ) tableView : ( UITableView * ) tableView cellForRowAtIndexPath : ( NSIndexPath * ) indexPath
2015-12-09 16:01:29 +00:00
{
2017-05-19 15:22:26 +00:00
// Sanity check
if ( tableView . tag ! = self . recentsDataSourceMode )
{
// The view controller of this table view is not the current selected one in the tab bar controller .
// Return a fake cell to prevent app from crashing
return [ [ UITableViewCell alloc ] init ] ;
}
2020-06-30 19:46:10 +00:00
if ( indexPath . section = = self . crossSigningBannerSection )
2020-06-30 15:31:44 +00:00
{
2020-06-30 19:46:10 +00:00
CrossSigningSetupBannerCell * crossSigningSetupBannerCell = [ tableView dequeueReusableCellWithIdentifier : CrossSigningSetupBannerCell . defaultReuseIdentifier forIndexPath : indexPath ] ;
crossSigningSetupBannerCell . delegate = self ;
return crossSigningSetupBannerCell ;
2020-06-30 15:31:44 +00:00
}
else if ( indexPath . section = = self . secureBackupBannerSection )
2019-01-31 18:52:32 +00:00
{
2020-06-26 11:07:53 +00:00
SecureBackupBannerCell * keyBackupBannerCell = [ tableView dequeueReusableCellWithIdentifier : SecureBackupBannerCell . defaultReuseIdentifier forIndexPath : indexPath ] ;
2020-06-25 15:52:36 +00:00
[ keyBackupBannerCell configureFor : self . secureBackupBannerDisplay ] ;
2019-02-01 08:51:57 +00:00
keyBackupBannerCell . delegate = self ;
return keyBackupBannerCell ;
2019-01-31 18:52:32 +00:00
}
else if ( indexPath . section = = directorySection )
2017-04-07 12:09:15 +00:00
{
2017-04-07 12:44:34 +00:00
NSIndexPath * indexPathInPublicRooms = [ NSIndexPath indexPathForRow : indexPath . row inSection : 0 ] ;
return [ _publicRoomsDirectoryDataSource tableView : tableView cellForRowAtIndexPath : indexPathInPublicRooms ] ;
2017-04-07 12:09:15 +00:00
}
else if ( self . droppingCellIndexPath && [ indexPath isEqual : self . droppingCellIndexPath ] )
2015-12-11 13:59:55 +00:00
{
2017-04-06 12:27:45 +00:00
static NSString * cellIdentifier = @ "RiotRecentsMovingCell" ;
2016-11-30 10:41:20 +00:00
2017-04-06 12:27:45 +00:00
UITableViewCell * cell = [ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleDefault reuseIdentifier : @ "RiotRecentsMovingCell" ] ;
2016-11-30 10:41:20 +00:00
// add an imageview of the cell .
// The image is a shot of the genuine cell .
// Thus , this cell has the same look as the genuine cell without computing it .
UIImageView * imageView = [ cell viewWithTag : [ cellIdentifier hash ] ] ;
if ( ! imageView || ( imageView ! = self . droppingCellBackGroundView ) )
2015-12-11 13:59:55 +00:00
{
2016-11-30 10:41:20 +00:00
if ( imageView )
2015-12-11 13:59:55 +00:00
{
2016-11-30 10:41:20 +00:00
[ imageView removeFromSuperview ] ;
2015-12-11 13:59:55 +00:00
}
2016-11-30 10:41:20 +00:00
self . droppingCellBackGroundView . tag = [ cellIdentifier hash ] ;
[ cell . contentView addSubview : self . droppingCellBackGroundView ] ;
2015-12-11 13:59:55 +00:00
}
2016-11-30 10:41:20 +00:00
self . droppingCellBackGroundView . frame = self . droppingCellBackGroundView . frame ;
cell . contentView . backgroundColor = [ UIColor clearColor ] ;
cell . backgroundColor = [ UIColor clearColor ] ;
return cell ;
2015-12-14 09:47:10 +00:00
}
2017-05-11 09:51:42 +00:00
else if ( ( indexPath . section = = conversationSection && ! conversationCellDataArray . count )
|| ( indexPath . section = = peopleSection && ! peopleCellDataArray . count ) )
2017-04-26 09:10:44 +00:00
{
MXKTableViewCell * tableViewCell = [ tableView dequeueReusableCellWithIdentifier : [ MXKTableViewCell defaultReuseIdentifier ] ] ;
if ( ! tableViewCell )
{
tableViewCell = [ [ MXKTableViewCell alloc ] init ] ;
2019-01-11 10:45:27 +00:00
tableViewCell . textLabel . textColor = ThemeService . shared . theme . textSecondaryColor ;
2017-04-26 09:10:44 +00:00
tableViewCell . textLabel . font = [ UIFont systemFontOfSize : 15.0 ] ;
tableViewCell . selectionStyle = UITableViewCellSelectionStyleNone ;
}
// Check whether a search session is in progress
2017-05-05 13:30:35 +00:00
if ( self . searchPatternsList )
2017-04-26 09:10:44 +00:00
{
tableViewCell . textLabel . text = NSLocalizedStringFromTable ( @ "search_no_result" , @ "Vector" , nil ) ;
}
2017-05-11 09:51:42 +00:00
else if ( _recentsDataSourceMode = = RecentsDataSourceModePeople || indexPath . section = = peopleSection )
2017-04-26 09:10:44 +00:00
{
tableViewCell . textLabel . text = NSLocalizedStringFromTable ( @ "people_no_conversation" , @ "Vector" , nil ) ;
}
else
{
tableViewCell . textLabel . text = NSLocalizedStringFromTable ( @ "room_recents_no_conversation" , @ "Vector" , nil ) ;
}
return tableViewCell ;
}
2015-12-14 09:47:10 +00:00
2016-04-28 14:26:37 +00:00
return [ super tableView : tableView cellForRowAtIndexPath : indexPath ] ;
2015-12-09 16:01:29 +00:00
}
2016-11-30 10:41:20 +00:00
- ( id < MXKRecentCellDataStoring > ) cellDataAtIndexPath : ( NSIndexPath * ) indexPath
2015-12-02 16:18:55 +00:00
{
id < MXKRecentCellDataStoring > cellData = nil ;
2016-11-30 10:41:20 +00:00
NSUInteger cellDataIndex = indexPath . row ;
NSInteger tableSection = indexPath . section ;
2015-12-11 13:59:55 +00:00
2016-11-30 10:41:20 +00:00
// Compute the actual cell data index by taking into account the current droppingCellIndexPath and hiddenCellIndexPath ( if any ) .
if ( [ self isMovingCellSection : tableSection ] && ( cellDataIndex > self . droppingCellIndexPath . row ) )
2015-12-11 13:59:55 +00:00
{
2016-11-30 10:41:20 +00:00
cellDataIndex - - ;
}
if ( [ self isHiddenCellSection : tableSection ] && ( cellDataIndex >= self . hiddenCellIndexPath . row ) )
{
cellDataIndex + + ;
2015-12-11 13:59:55 +00:00
}
2015-12-02 16:18:55 +00:00
2016-11-30 10:41:20 +00:00
if ( tableSection = = favoritesSection )
2015-12-02 16:18:55 +00:00
{
2016-11-30 10:41:20 +00:00
if ( cellDataIndex < favoriteCellDataArray . count )
2016-11-28 17:28:03 +00:00
{
2019-01-07 23:24:11 +00:00
cellData = favoriteCellDataArray [ cellDataIndex ] ;
2016-11-28 17:28:03 +00:00
}
2015-12-02 16:18:55 +00:00
}
2017-05-11 09:51:42 +00:00
else if ( tableSection = = peopleSection )
{
if ( cellDataIndex < peopleCellDataArray . count )
{
2019-01-07 23:24:11 +00:00
cellData = peopleCellDataArray [ cellDataIndex ] ;
2017-05-11 09:51:42 +00:00
}
}
2016-11-30 10:41:20 +00:00
else if ( tableSection = = conversationSection )
2015-12-02 16:18:55 +00:00
{
2016-11-30 10:41:20 +00:00
if ( cellDataIndex < conversationCellDataArray . count )
2016-11-28 17:28:03 +00:00
{
2019-01-07 23:24:11 +00:00
cellData = conversationCellDataArray [ cellDataIndex ] ;
2016-11-28 17:28:03 +00:00
}
2015-12-02 16:18:55 +00:00
}
2016-11-30 10:41:20 +00:00
else if ( tableSection = = lowPrioritySection )
2015-12-02 16:18:55 +00:00
{
2016-11-30 10:41:20 +00:00
if ( cellDataIndex < lowPriorityCellDataArray . count )
2016-11-28 17:28:03 +00:00
{
2019-01-07 23:24:11 +00:00
cellData = lowPriorityCellDataArray [ cellDataIndex ] ;
2016-11-28 17:28:03 +00:00
}
2015-12-02 16:18:55 +00:00
}
2018-08-23 14:50:14 +00:00
else if ( tableSection = = serverNoticeSection )
{
if ( cellDataIndex < serverNoticeCellDataArray . count )
{
2019-01-07 23:24:11 +00:00
cellData = serverNoticeCellDataArray [ cellDataIndex ] ;
2018-08-23 14:50:14 +00:00
}
}
2016-11-30 10:41:20 +00:00
else if ( tableSection = = invitesSection )
2015-12-09 15:09:46 +00:00
{
2016-11-30 10:41:20 +00:00
if ( cellDataIndex < invitesCellDataArray . count )
2016-11-28 17:28:03 +00:00
{
2019-01-07 23:24:11 +00:00
cellData = invitesCellDataArray [ cellDataIndex ] ;
2016-11-28 17:28:03 +00:00
}
2015-12-09 15:09:46 +00:00
}
2015-12-02 16:18:55 +00:00
return cellData ;
}
- ( CGFloat ) cellHeightAtIndexPath : ( NSIndexPath * ) indexPath
{
2017-04-07 12:09:15 +00:00
if ( indexPath . section = = directorySection )
{
2017-04-26 09:10:44 +00:00
return [ _publicRoomsDirectoryDataSource cellHeightAtIndexPath : indexPath ] ;
2017-04-07 12:09:15 +00:00
}
2015-12-16 07:59:40 +00:00
if ( self . droppingCellIndexPath && [ indexPath isEqual : self . droppingCellIndexPath ] )
2015-12-11 13:59:55 +00:00
{
2015-12-16 07:59:40 +00:00
return self . droppingCellBackGroundView . frame . size . height ;
2015-12-11 13:59:55 +00:00
}
2017-05-12 15:39:05 +00:00
if ( ( indexPath . section = = conversationSection && ! conversationCellDataArray . count )
|| ( indexPath . section = = peopleSection && ! peopleCellDataArray . count ) )
2017-04-26 09:10:44 +00:00
{
return 50.0 ;
}
2015-12-11 13:59:55 +00:00
2015-12-07 10:50:13 +00:00
// Override this method here to use our own cellDataAtIndexPath
2015-12-02 16:18:55 +00:00
id < MXKRecentCellDataStoring > cellData = [ self cellDataAtIndexPath : indexPath ] ;
2015-12-07 10:50:13 +00:00
if ( cellData && self . delegate )
2015-12-02 16:18:55 +00:00
{
2015-12-07 10:50:13 +00:00
Class < MXKCellRendering > class = [ self . delegate cellViewClassForCellData : cellData ] ;
2015-12-09 15:09:46 +00:00
2015-12-02 16:18:55 +00:00
return [ class heightForCellData : cellData withMaximumWidth : 0 ] ;
}
return 0 ;
}
2017-05-19 15:22:26 +00:00
- ( BOOL ) tableView : ( UITableView * ) tableView canEditRowAtIndexPath : ( NSIndexPath * ) indexPath
{
// Sanity check
if ( tableView . tag ! = self . recentsDataSourceMode )
{
// The view controller of this table view is not the current selected one in the tab bar controller .
return NO ;
}
// Invited rooms are not editable .
return ( indexPath . section ! = invitesSection ) ;
}
2017-04-06 12:27:45 +00:00
# pragma mark -
2015-12-10 12:41:03 +00:00
- ( NSInteger ) cellIndexPosWithRoomId : ( NSString * ) roomId andMatrixSession : ( MXSession * ) matrixSession within : ( NSMutableArray * ) cellDataArray
{
if ( roomId && matrixSession && cellDataArray . count )
{
for ( int index = 0 ; index < cellDataArray . count ; index + + )
{
2019-01-07 23:24:11 +00:00
id < MXKRecentCellDataStoring > cellDataStoring = cellDataArray [ index ] ;
2015-12-10 12:41:03 +00:00
2017-01-11 08:58:09 +00:00
if ( [ roomId isEqualToString : cellDataStoring . roomSummary . roomId ] && ( matrixSession = = cellDataStoring . roomSummary . room . mxSession ) )
2015-12-10 12:41:03 +00:00
{
return index ;
}
}
}
return NSNotFound ;
}
- ( NSIndexPath * ) cellIndexPathWithRoomId : ( NSString * ) roomId andMatrixSession : ( MXSession * ) matrixSession
{
NSIndexPath * indexPath = nil ;
2016-04-12 07:20:38 +00:00
NSInteger index ;
2015-12-10 12:41:03 +00:00
2016-04-12 07:20:38 +00:00
if ( invitesSection >= 0 )
2015-12-10 12:41:03 +00:00
{
index = [ self cellIndexPosWithRoomId : roomId andMatrixSession : matrixSession within : invitesCellDataArray ] ;
if ( index ! = NSNotFound )
{
2016-04-12 07:20:38 +00:00
// Check whether the invitations are shrinked
if ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _INVITES )
{
return nil ;
}
2015-12-10 12:41:03 +00:00
indexPath = [ NSIndexPath indexPathForRow : index inSection : invitesSection ] ;
}
}
if ( ! indexPath && ( favoritesSection >= 0 ) )
{
index = [ self cellIndexPosWithRoomId : roomId andMatrixSession : matrixSession within : favoriteCellDataArray ] ;
if ( index ! = NSNotFound )
{
2016-04-12 07:20:38 +00:00
// Check whether the favorites are shrinked
if ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _FAVORITES )
{
return nil ;
}
2015-12-10 12:41:03 +00:00
indexPath = [ NSIndexPath indexPathForRow : index inSection : favoritesSection ] ;
}
}
2017-05-11 09:51:42 +00:00
if ( ! indexPath && ( peopleSection >= 0 ) )
{
index = [ self cellIndexPosWithRoomId : roomId andMatrixSession : matrixSession within : peopleCellDataArray ] ;
if ( index ! = NSNotFound )
{
// Check whether the favorites are shrinked
if ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _PEOPLE )
{
return nil ;
}
indexPath = [ NSIndexPath indexPathForRow : index inSection : peopleSection ] ;
}
}
2015-12-10 12:41:03 +00:00
if ( ! indexPath && ( conversationSection >= 0 ) )
{
index = [ self cellIndexPosWithRoomId : roomId andMatrixSession : matrixSession within : conversationCellDataArray ] ;
if ( index ! = NSNotFound )
{
2016-04-12 07:20:38 +00:00
// Check whether the conversations are shrinked
if ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _CONVERSATIONS )
{
return nil ;
}
2015-12-10 12:41:03 +00:00
indexPath = [ NSIndexPath indexPathForRow : index inSection : conversationSection ] ;
}
}
if ( ! indexPath && ( lowPrioritySection >= 0 ) )
{
index = [ self cellIndexPosWithRoomId : roomId andMatrixSession : matrixSession within : lowPriorityCellDataArray ] ;
if ( index ! = NSNotFound )
{
2016-04-12 07:20:38 +00:00
// Check whether the low priority rooms are shrinked
if ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _LOWPRIORITY )
{
return nil ;
}
2015-12-10 12:41:03 +00:00
indexPath = [ NSIndexPath indexPathForRow : index inSection : lowPrioritySection ] ;
}
}
2018-08-23 14:50:14 +00:00
if ( ! indexPath && ( serverNoticeSection >= 0 ) )
{
index = [ self cellIndexPosWithRoomId : roomId andMatrixSession : matrixSession within : serverNoticeCellDataArray ] ;
if ( index ! = NSNotFound )
{
// Check whether the low priority rooms are shrinked
if ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _SERVERNOTICE )
{
return nil ;
}
indexPath = [ NSIndexPath indexPathForRow : index inSection : serverNoticeSection ] ;
}
}
2015-12-10 12:41:03 +00:00
return indexPath ;
}
2015-12-02 16:18:55 +00:00
# pragma mark - MXKDataSourceDelegate
2015-12-02 16:38:10 +00:00
- ( void ) refreshRoomsSections
2015-12-02 16:18:55 +00:00
{
2019-02-18 17:25:50 +00:00
NSDate * startDate = [ NSDate date ] ;
2017-04-06 12:27:45 +00:00
[ invitesCellDataArray removeAllObjects ] ;
[ favoriteCellDataArray removeAllObjects ] ;
2017-05-11 09:51:42 +00:00
[ peopleCellDataArray removeAllObjects ] ;
2017-04-06 12:27:45 +00:00
[ conversationCellDataArray removeAllObjects ] ;
[ lowPriorityCellDataArray removeAllObjects ] ;
2018-08-23 14:50:14 +00:00
[ serverNoticeCellDataArray removeAllObjects ] ;
2015-12-03 08:37:45 +00:00
2017-04-28 12:06:58 +00:00
_missedFavouriteDiscussionsCount = _missedHighlightFavouriteDiscussionsCount = 0 ;
_missedDirectDiscussionsCount = _missedHighlightDirectDiscussionsCount = 0 ;
_missedGroupDiscussionsCount = _missedHighlightGroupDiscussionsCount = 0 ;
2020-06-25 15:52:36 +00:00
secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1 ;
2019-01-31 18:52:32 +00:00
2017-04-06 12:27:45 +00:00
if ( displayedRecentsDataSourceArray . count > 0 )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
// FIXME manage multi accounts
2019-01-07 23:24:11 +00:00
MXKSessionRecentsDataSource * recentsDataSource = displayedRecentsDataSourceArray [ 0 ] ;
2015-12-02 17:10:22 +00:00
MXSession * session = recentsDataSource . mxSession ;
2015-12-02 16:18:55 +00:00
NSInteger count = recentsDataSource . numberOfCells ;
2017-04-28 12:06:58 +00:00
for ( int index = 0 ; index < count ; index + + )
2015-12-02 16:18:55 +00:00
{
2017-04-28 12:06:58 +00:00
id < MXKRecentCellDataStoring > recentCellDataStoring = [ recentsDataSource cellDataAtIndex : index ] ;
MXRoom * room = recentCellDataStoring . roomSummary . room ;
if ( _recentsDataSourceMode = = RecentsDataSourceModeHome )
2015-12-02 16:18:55 +00:00
{
2018-08-23 14:50:14 +00:00
if ( room . accountData . tags [ kMXRoomTagServerNotice ] )
{
[ serverNoticeCellDataArray addObject : recentCellDataStoring ] ;
}
else if ( room . accountData . tags [ kMXRoomTagFavourite ] )
2017-04-06 12:27:45 +00:00
{
[ favoriteCellDataArray addObject : recentCellDataStoring ] ;
}
else if ( room . accountData . tags [ kMXRoomTagLowPriority ] )
2015-12-02 17:10:22 +00:00
{
2017-04-06 12:27:45 +00:00
[ lowPriorityCellDataArray addObject : recentCellDataStoring ] ;
}
2018-07-17 16:00:56 +00:00
else if ( room . summary . membership = = MXMembershipInvite )
2017-04-06 12:27:45 +00:00
{
[ invitesCellDataArray addObject : recentCellDataStoring ] ;
}
2017-05-11 09:51:42 +00:00
else if ( room . isDirect )
{
[ peopleCellDataArray addObject : recentCellDataStoring ] ;
}
2017-04-06 12:27:45 +00:00
else
{
[ conversationCellDataArray addObject : recentCellDataStoring ] ;
2015-12-02 17:10:22 +00:00
}
2015-12-02 16:18:55 +00:00
}
2017-04-28 12:06:58 +00:00
else if ( _recentsDataSourceMode = = RecentsDataSourceModeFavourites )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
// Keep only the favourites rooms .
if ( room . accountData . tags [ kMXRoomTagFavourite ] )
2015-12-02 17:10:22 +00:00
{
2017-04-06 12:27:45 +00:00
[ favoriteCellDataArray addObject : recentCellDataStoring ] ;
2015-12-02 17:10:22 +00:00
}
2015-12-02 16:18:55 +00:00
}
2017-04-28 12:06:58 +00:00
else if ( _recentsDataSourceMode = = RecentsDataSourceModePeople )
2015-12-09 15:09:46 +00:00
{
2017-06-08 13:07:43 +00:00
// Keep only the direct rooms which are not low priority
2017-06-08 14:01:24 +00:00
if ( room . isDirect && ! room . accountData . tags [ kMXRoomTagLowPriority ] )
2015-12-09 15:09:46 +00:00
{
2018-07-17 16:00:56 +00:00
if ( room . summary . membership = = MXMembershipInvite )
2017-04-06 12:27:45 +00:00
{
2017-06-08 13:19:34 +00:00
[ invitesCellDataArray addObject : recentCellDataStoring ] ;
}
else
{
[ conversationCellDataArray addObject : recentCellDataStoring ] ;
2017-04-06 12:27:45 +00:00
}
2015-12-09 15:09:46 +00:00
}
}
2017-04-28 12:06:58 +00:00
else if ( _recentsDataSourceMode = = RecentsDataSourceModeRooms )
2015-12-02 16:18:55 +00:00
{
2017-04-11 15:58:59 +00:00
// Consider only non direct rooms .
if ( ! room . isDirect )
2017-04-06 13:49:47 +00:00
{
2017-05-02 12:59:21 +00:00
// Keep only the invites , the favourites and the rooms without tag
2018-07-17 16:00:56 +00:00
if ( room . summary . membership = = MXMembershipInvite )
2017-04-11 15:58:59 +00:00
{
[ invitesCellDataArray addObject : recentCellDataStoring ] ;
}
2017-05-02 12:59:21 +00:00
else if ( ! room . accountData . tags . count || room . accountData . tags [ kMXRoomTagFavourite ] )
2017-04-11 15:58:59 +00:00
{
[ conversationCellDataArray addObject : recentCellDataStoring ] ;
}
2017-04-06 12:27:45 +00:00
}
2015-12-02 16:18:55 +00:00
}
2017-04-28 12:06:58 +00:00
// Update missed conversations counts
NSUInteger notificationCount = recentCellDataStoring . roomSummary . notificationCount ;
// Ignore the regular notification count if the room is in ' mentions only " mode at the Riot level .
if ( room . isMentionsOnly )
{
// Only the highlighted missed messages must be considered here .
notificationCount = recentCellDataStoring . roomSummary . highlightCount ;
}
if ( notificationCount )
{
if ( room . accountData . tags [ kMXRoomTagFavourite ] )
{
_missedFavouriteDiscussionsCount + + ;
if ( recentCellDataStoring . roomSummary . highlightCount )
{
_missedHighlightFavouriteDiscussionsCount + + ;
}
}
if ( room . isDirect )
{
_missedDirectDiscussionsCount + + ;
if ( recentCellDataStoring . roomSummary . highlightCount )
{
_missedHighlightDirectDiscussionsCount + + ;
}
}
2017-05-02 12:59:21 +00:00
else if ( ! room . accountData . tags . count || room . accountData . tags [ kMXRoomTagFavourite ] )
2017-04-28 12:06:58 +00:00
{
_missedGroupDiscussionsCount + + ;
if ( recentCellDataStoring . roomSummary . highlightCount )
{
_missedHighlightGroupDiscussionsCount + + ;
}
}
}
2018-07-17 16:00:56 +00:00
else if ( room . summary . membership = = MXMembershipInvite )
2017-04-28 12:06:58 +00:00
{
if ( room . isDirect )
{
_missedDirectDiscussionsCount + + ;
}
else
{
_missedGroupDiscussionsCount + + ;
}
}
2015-12-02 16:18:55 +00:00
}
2017-06-13 16:43:03 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModeHome )
2015-12-02 16:18:55 +00:00
{
2018-07-02 12:51:47 +00:00
BOOL pinMissedNotif = RiotSettings . shared . pinRoomsWithMissedNotificationsOnHome ;
BOOL pinUnread = RiotSettings . shared . pinRoomsWithUnreadMessagesOnHome ;
2017-06-16 13:18:33 +00:00
NSComparator comparator = nil ;
if ( pinMissedNotif )
{
// Sort each rooms collection by considering first the rooms with some missed notifs , the rooms with unread , then the others .
comparator = ^ NSComparisonResult ( id < MXKRecentCellDataStoring > recentCellData1 , id < MXKRecentCellDataStoring > recentCellData2 ) {
2021-03-02 20:56:50 +00:00
if ( recentCellData1 . roomSummary . room . sentStatus ! = MXRoomSentStatusOk
&& recentCellData2 . roomSummary . room . sentStatus = = MXRoomSentStatusOk )
{
return NSOrderedAscending ;
}
if ( recentCellData2 . roomSummary . room . sentStatus ! = MXRoomSentStatusOk
&& recentCellData1 . roomSummary . room . sentStatus = = MXRoomSentStatusOk )
{
return NSOrderedDescending ;
}
2017-06-16 13:18:33 +00:00
if ( recentCellData1 . highlightCount )
2017-06-13 16:43:03 +00:00
{
2017-06-16 13:18:33 +00:00
if ( recentCellData2 . highlightCount )
{
return NSOrderedSame ;
}
else
{
return NSOrderedAscending ;
}
2017-06-13 16:43:03 +00:00
}
2017-06-16 13:18:33 +00:00
else if ( recentCellData2 . highlightCount )
2017-06-13 16:43:03 +00:00
{
2017-06-16 13:18:33 +00:00
return NSOrderedDescending ;
2017-06-13 16:43:03 +00:00
}
2017-06-16 13:18:33 +00:00
else if ( recentCellData1 . notificationCount )
2017-06-13 16:43:03 +00:00
{
2017-06-16 13:18:33 +00:00
if ( recentCellData2 . notificationCount )
{
return NSOrderedSame ;
}
else
{
return NSOrderedAscending ;
}
2017-06-13 16:43:03 +00:00
}
2017-06-16 13:18:33 +00:00
else if ( recentCellData2 . notificationCount )
2017-06-13 16:43:03 +00:00
{
2017-06-16 13:18:33 +00:00
return NSOrderedDescending ;
2017-06-13 16:43:03 +00:00
}
2017-06-16 13:18:33 +00:00
else if ( pinUnread )
2017-06-13 16:43:03 +00:00
{
2017-06-16 13:18:33 +00:00
if ( recentCellData1 . hasUnread )
{
if ( recentCellData2 . hasUnread )
{
return NSOrderedSame ;
}
else
{
return NSOrderedAscending ;
}
}
else if ( recentCellData2 . hasUnread )
{
return NSOrderedDescending ;
}
2017-06-13 16:43:03 +00:00
}
2017-06-16 13:18:33 +00:00
return NSOrderedSame ;
} ;
}
else if ( pinUnread )
{
// Sort each rooms collection by considering first the rooms with some unread messages then the others .
comparator = ^ NSComparisonResult ( id < MXKRecentCellDataStoring > recentCellData1 , id < MXKRecentCellDataStoring > recentCellData2 ) {
2021-03-02 20:56:50 +00:00
if ( recentCellData1 . roomSummary . room . sentStatus ! = MXRoomSentStatusOk
&& recentCellData2 . roomSummary . room . sentStatus = = MXRoomSentStatusOk )
{
return NSOrderedAscending ;
}
if ( recentCellData2 . roomSummary . room . sentStatus ! = MXRoomSentStatusOk
&& recentCellData1 . roomSummary . room . sentStatus = = MXRoomSentStatusOk )
{
return NSOrderedDescending ;
}
2017-06-16 13:18:33 +00:00
if ( recentCellData1 . hasUnread )
2017-06-13 16:43:03 +00:00
{
2017-06-16 13:18:33 +00:00
if ( recentCellData2 . hasUnread )
{
return NSOrderedSame ;
}
else
{
return NSOrderedAscending ;
}
2017-06-13 16:43:03 +00:00
}
2017-06-16 13:18:33 +00:00
else if ( recentCellData2 . hasUnread )
{
return NSOrderedDescending ;
}
return NSOrderedSame ;
} ;
}
2017-06-13 16:43:03 +00:00
2017-06-16 13:18:33 +00:00
if ( comparator )
{
// Sort the rooms collections
[ favoriteCellDataArray sortUsingComparator : comparator ] ;
[ peopleCellDataArray sortUsingComparator : comparator ] ;
[ conversationCellDataArray sortUsingComparator : comparator ] ;
[ lowPriorityCellDataArray sortUsingComparator : comparator ] ;
2018-08-23 14:50:14 +00:00
[ serverNoticeCellDataArray sortUsingComparator : comparator ] ;
2017-06-16 13:18:33 +00:00
}
2015-12-02 16:18:55 +00:00
}
2017-06-13 16:43:03 +00:00
else if ( favoriteCellDataArray . count > 0 && _recentsDataSourceMode = = RecentsDataSourceModeFavourites )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
// Sort them according to their tag order
2017-06-13 16:43:03 +00:00
[ favoriteCellDataArray sortUsingComparator : ^ NSComparisonResult ( id < MXKRecentCellDataStoring > recentCellData1 , id < MXKRecentCellDataStoring > recentCellData2 ) {
2017-04-06 12:27:45 +00:00
2017-06-13 16:43:03 +00:00
return [ session compareRoomsByTag : kMXRoomTagFavourite room1 : recentCellData1 . roomSummary . room room2 : recentCellData2 . roomSummary . room ] ;
2017-04-06 12:27:45 +00:00
} ] ;
2021-03-02 20:56:50 +00:00
} else if ( conversationCellDataArray . count > 0 && ( _recentsDataSourceMode = = RecentsDataSourceModeRooms || _recentsDataSourceMode = = RecentsDataSourceModePeople ) )
{
[ conversationCellDataArray sortUsingComparator : ^ NSComparisonResult ( id < MXKRecentCellDataStoring > recentCellData1 , id < MXKRecentCellDataStoring > recentCellData2 ) {
if ( recentCellData1 . roomSummary . room . sentStatus ! = MXRoomSentStatusOk
&& recentCellData2 . roomSummary . room . sentStatus = = MXRoomSentStatusOk )
{
return NSOrderedAscending ;
}
if ( recentCellData2 . roomSummary . room . sentStatus ! = MXRoomSentStatusOk
&& recentCellData1 . roomSummary . room . sentStatus = = MXRoomSentStatusOk )
{
return NSOrderedDescending ;
}
return NSOrderedAscending ;
} ] ;
2015-12-02 16:18:55 +00:00
}
}
2019-02-18 17:25:50 +00:00
NSLog ( @ "[RecentsDataSource] refreshRoomsSections: Done in %.0fms" , [ [ NSDate date ] timeIntervalSinceDate : startDate ] * 1000 ) ;
2015-12-02 16:38:10 +00:00
}
- ( void ) dataSource : ( MXKDataSource * ) dataSource didCellChange : ( id ) changes
{
2015-12-16 08:17:28 +00:00
// Refresh is disabled during drag & drop animation
2015-12-16 07:59:40 +00:00
if ( self . droppingCellIndexPath )
2015-12-11 14:30:26 +00:00
{
return ;
}
2015-12-04 08:02:02 +00:00
// FIXME : manage multi accounts
// to manage multi accounts
// this method in MXKInterleavedRecentsDataSource must be split in two parts
// 1 - the intervealing cells method
// 2 - [ super dataSource : dataSource didCellChange : changes ] call .
// the [ self refreshRoomsSections ] call should be done at the end of the 1 - method
// so a dedicated method must be implemented in MXKInterleavedRecentsDataSource
// this class will inherit of this new method
// 1 - call [ super thisNewMethod ]
// 2 - call [ self refreshRoomsSections ]
2015-12-14 07:29:01 +00:00
// refresh the sections
2015-12-03 08:06:40 +00:00
[ self refreshRoomsSections ] ;
2015-12-02 16:18:55 +00:00
// Call super to keep update readyRecentsDataSourceArray .
[ super dataSource : dataSource didCellChange : changes ] ;
}
2017-04-06 12:27:45 +00:00
# pragma mark - Drag & Drop handling
- ( BOOL ) isMovingCellSection : ( NSInteger ) section
{
return self . droppingCellIndexPath && ( self . droppingCellIndexPath . section = = section ) ;
}
- ( BOOL ) isHiddenCellSection : ( NSInteger ) section
{
return self . hiddenCellIndexPath && ( self . hiddenCellIndexPath . section = = section ) ;
}
2016-04-12 07:20:38 +00:00
# pragma mark - Action
- ( IBAction ) onButtonPressed : ( id ) sender
{
if ( [ sender isKindOfClass : [ UIButton class ] ] )
{
UIButton * shrinkButton = ( UIButton * ) sender ;
NSInteger selectedSectionBit = shrinkButton . tag ;
if ( shrinkedSectionsBitMask & selectedSectionBit )
{
// Disclose the section
shrinkedSectionsBitMask & = ~ selectedSectionBit ;
}
else
{
// Shrink this section
shrinkedSectionsBitMask | = selectedSectionBit ;
}
// Inform the delegate about the update
[ self . delegate dataSource : self didCellChange : nil ] ;
}
}
2017-03-29 08:37:53 +00:00
- ( IBAction ) onPublicRoomsSearchPatternUpdate : ( id ) sender
{
if ( publicRoomsTriggerTimer )
{
NSString * searchPattern = publicRoomsTriggerTimer . userInfo ;
[ publicRoomsTriggerTimer invalidate ] ;
publicRoomsTriggerTimer = nil ;
_publicRoomsDirectoryDataSource . searchPattern = searchPattern ;
2017-04-21 15:58:41 +00:00
[ _publicRoomsDirectoryDataSource paginate : nil failure : nil ] ;
2017-03-29 08:37:53 +00:00
}
}
2017-04-20 16:06:49 +00:00
# pragma mark - Action
- ( IBAction ) onDirectoryServerPickerTap : ( UITapGestureRecognizer * ) sender
{
[ self . delegate dataSource : self didRecognizeAction : kRecentsDataSourceTapOnDirectoryServerChange inCell : nil userInfo : nil ] ;
}
2015-11-20 17:14:15 +00:00
# pragma mark - Override MXKDataSource
- ( void ) destroy
{
[ super destroy ] ;
2017-03-29 08:37:53 +00:00
[ publicRoomsTriggerTimer invalidate ] ;
publicRoomsTriggerTimer = nil ;
2015-11-20 17:14:15 +00:00
}
2015-12-16 15:29:34 +00:00
# pragma mark - Override MXKRecentsDataSource
2017-04-06 12:27:45 +00:00
2015-12-16 15:29:34 +00:00
- ( void ) searchWithPatterns : ( NSArray * ) patternsList
{
[ super searchWithPatterns : patternsList ] ;
2015-12-21 10:13:46 +00:00
if ( _publicRoomsDirectoryDataSource )
2015-12-16 15:29:34 +00:00
{
2017-03-29 08:37:53 +00:00
NSString * searchPattern = [ patternsList componentsJoinedByString : @ " " ] ;
// Do not send a / publicRooms request for every keystroke
// Let user finish typing
[ publicRoomsTriggerTimer invalidate ] ;
publicRoomsTriggerTimer = [ NSTimer scheduledTimerWithTimeInterval : 0.7 target : self selector : @ selector ( onPublicRoomsSearchPatternUpdate : ) userInfo : searchPattern repeats : NO ] ;
2015-12-16 15:29:34 +00:00
}
}
2015-12-11 10:50:13 +00:00
# pragma mark - drag and drop managemenent
- ( BOOL ) isDraggableCellAt : ( NSIndexPath * ) path
{
2017-04-06 12:27:45 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModePeople || _recentsDataSourceMode = = RecentsDataSourceModeRooms )
{
return NO ;
}
2018-08-23 14:50:14 +00:00
return ( path && ( ( path . section = = favoritesSection ) || ( path . section = = peopleSection ) || ( path . section = = lowPrioritySection ) || ( path . section = = serverNoticeSection ) || ( path . section = = conversationSection ) ) ) ;
2015-12-11 10:50:13 +00:00
}
- ( BOOL ) canCellMoveFrom : ( NSIndexPath * ) oldPath to : ( NSIndexPath * ) newPath
{
BOOL res = [ self isDraggableCellAt : oldPath ] && [ self isDraggableCellAt : newPath ] ;
// the both index pathes are movable
if ( res )
{
2015-12-11 15:20:26 +00:00
// only the favorites cell can be moved within the same section
res & = ( oldPath . section = = favoritesSection ) || ( newPath . section ! = oldPath . section ) ;
2015-12-11 10:50:13 +00:00
// other cases ?
}
return res ;
}
- ( NSString * ) roomTagAt : ( NSIndexPath * ) path
{
if ( path . section = = favoritesSection )
{
return kMXRoomTagFavourite ;
}
else if ( path . section = = lowPrioritySection )
{
return kMXRoomTagLowPriority ;
}
2018-08-23 14:50:14 +00:00
else if ( path . section = = serverNoticeSection )
{
return kMXRoomTagServerNotice ;
}
2015-12-11 10:50:13 +00:00
return nil ;
}
2019-01-05 02:28:03 +00:00
- ( void ) moveRoomCell : ( MXRoom * ) room from : ( NSIndexPath * ) oldPath to : ( NSIndexPath * ) newPath success : ( void ( ^ ) ( void ) ) moveSuccess failure : ( void ( ^ ) ( NSError * error ) ) moveFailure ;
2015-12-11 10:50:13 +00:00
{
2015-12-21 09:35:48 +00:00
NSLog ( @ "[RecentsDataSource] moveCellFrom (%tu, %tu) to (%tu, %tu)" , oldPath . section , oldPath . row , newPath . section , newPath . row ) ;
2015-12-11 11:03:05 +00:00
2015-12-11 10:50:13 +00:00
if ( [ self canCellMoveFrom : oldPath to : newPath ] && ! [ newPath isEqual : oldPath ] )
{
2017-05-11 09:51:42 +00:00
if ( newPath . section = = peopleSection )
{
[ room setIsDirect : YES
withUserId : nil
success : moveSuccess
failure : ^ ( NSError * error ) {
NSLog ( @ "[RecentsDataSource] Failed to mark as direct" ) ;
if ( moveFailure )
{
moveFailure ( error ) ;
}
[ self forceRefresh ] ;
// Notify user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
}
else
{
NSString * oldRoomTag = [ self roomTagAt : oldPath ] ;
NSString * dstRoomTag = [ self roomTagAt : newPath ] ;
NSUInteger oldPos = ( oldPath . section = = newPath . section ) ? oldPath . row : NSNotFound ;
NSString * tagOrder = [ room . mxSession tagOrderToBeAtIndex : newPath . row from : oldPos withTag : dstRoomTag ] ;
2018-07-16 20:30:55 +00:00
NSLog ( @ "[RecentsDataSource] Update the room %@ [%@] tag from %@ to %@ with tag order %@" , room . roomId , room . summary . displayname , oldRoomTag , dstRoomTag , tagOrder ) ;
2017-05-11 09:51:42 +00:00
[ room replaceTag : oldRoomTag
byTag : dstRoomTag
withOrder : tagOrder
success : ^ {
NSLog ( @ "[RecentsDataSource] move is done" ) ;
if ( moveSuccess )
{
moveSuccess ( ) ;
}
// wait the server echo to reload the tableview .
} failure : ^ ( NSError * error ) {
2018-07-16 20:30:55 +00:00
NSLog ( @ "[RecentsDataSource] Failed to update the tag %@ of room (%@)" , dstRoomTag , room . roomId ) ;
2017-05-11 09:51:42 +00:00
if ( moveFailure )
{
moveFailure ( error ) ;
}
[ self forceRefresh ] ;
// Notify user
[ [ AppDelegate theDelegate ] showErrorAsAlert : error ] ;
} ] ;
}
2015-12-11 10:50:13 +00:00
}
2015-12-11 11:03:05 +00:00
else
{
NSLog ( @ "[RecentsDataSource] cannot move this cell" ) ;
2015-12-11 14:30:26 +00:00
if ( moveFailure )
{
moveFailure ( nil ) ;
}
2015-12-14 12:06:25 +00:00
2017-04-06 12:27:45 +00:00
[ self forceRefresh ] ;
2015-12-11 11:03:05 +00:00
}
2015-12-11 10:50:13 +00:00
}
2020-06-30 15:31:44 +00:00
# pragma mark - SecureBackupSetupBannerCellDelegate
2019-01-31 18:52:32 +00:00
2020-06-26 11:07:53 +00:00
- ( void ) secureBackupBannerCellDidTapCloseAction : ( SecureBackupBannerCell * _Nonnull ) cell
2019-01-31 18:52:32 +00:00
{
2020-06-25 15:52:36 +00:00
[ self hideKeyBackupBannerWithDisplay : self . secureBackupBannerDisplay ] ;
2019-01-31 18:52:32 +00:00
}
2020-06-30 19:46:10 +00:00
# pragma mark - CrossSigningSetupBannerCellDelegate
2020-06-30 15:31:44 +00:00
2020-06-30 19:46:10 +00:00
- ( void ) crossSigningSetupBannerCellDidTapCloseAction : ( CrossSigningSetupBannerCell * ) cell
2020-06-30 15:31:44 +00:00
{
2020-06-30 19:46:10 +00:00
[ self hideCrossSigningBannerWithDisplay : self . crossSigningBannerDisplay ] ;
2020-06-30 15:31:44 +00:00
}
2015-11-20 17:14:15 +00:00
@ end