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"
2015-11-20 17:14:15 +00:00
2017-03-08 15:14:41 +00:00
# import "RiotDesignValues.h"
2015-12-04 16:45:56 +00:00
2017-03-09 10:50:12 +00:00
# import "MXRoom+Riot.h"
2015-12-21 09:35:48 +00:00
2017-04-07 12:09:15 +00:00
# import "DirectoryRecentTableViewCell.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
2015-12-02 16:18:55 +00:00
@ interface RecentsDataSource ( )
{
2015-12-09 15:09:46 +00:00
NSMutableArray * invitesCellDataArray ;
2015-12-04 08:02:02 +00:00
NSMutableArray * favoriteCellDataArray ;
NSMutableArray * conversationCellDataArray ;
NSMutableArray * lowPriorityCellDataArray ;
2015-12-02 16:18:55 +00:00
2016-04-12 07:20:38 +00:00
NSInteger shrinkedSectionsBitMask ;
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
}
@ end
2015-11-20 17:14:15 +00:00
@ implementation RecentsDataSource
2017-04-11 15:58:59 +00:00
@ synthesize directorySection , invitesSection , favoritesSection , conversationSection , lowPrioritySection ;
2015-12-16 07:59:40 +00:00
@ synthesize hiddenCellIndexPath , droppingCellIndexPath , droppingCellBackGroundView ;
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 ] ;
lowPriorityCellDataArray = [ [ NSMutableArray alloc ] init ] ;
2017-04-06 12:27:45 +00:00
conversationCellDataArray = [ [ NSMutableArray alloc ] init ] ;
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 ;
conversationSection = -1 ;
lowPrioritySection = -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
// 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
{
self . delegate = delegate ;
self . recentsDataSourceMode = recentsDataSourceMode ;
}
- ( void ) setRecentsDataSourceMode : ( RecentsDataSourceMode ) recentsDataSourceMode
{
_recentsDataSourceMode = recentsDataSourceMode ;
[ self forceRefresh ] ;
2017-04-07 13:44:29 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModeRooms )
{
// Make _publicRoomsDirectoryDataSource start loading data
_publicRoomsDirectoryDataSource . searchPattern = nil ;
}
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 ] ;
_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
{
id roomTagListener = [ roomTagsListenerByUserId objectForKey : matrixSession . myUser . userId ] ;
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
} ) ;
}
} ] ;
2016-03-10 17:00:40 +00:00
[ roomTagsListenerByUserId setObject : roomTagsListener forKey : dataSource . mxSession . myUser . userId ] ;
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-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 )
{
2017-04-11 15:58:59 +00:00
directorySection = favoritesSection = conversationSection = lowPrioritySection = invitesSection = -1 ;
if ( invitesCellDataArray . count > 0 )
{
invitesSection = sectionsCount + + ;
}
if ( favoriteCellDataArray . count > 0 )
{
favoritesSection = sectionsCount + + ;
}
if ( conversationCellDataArray . count > 0 )
{
conversationSection = sectionsCount + + ;
}
if ( _recentsDataSourceMode = = RecentsDataSourceModeRooms )
{
// Add the directory section after "ROOMS"
directorySection = sectionsCount + + ;
}
if ( lowPriorityCellDataArray . count > 0 )
{
lowPrioritySection = 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
{
NSUInteger count = 0 ;
2017-04-07 12:09:15 +00:00
2017-04-06 12:27:45 +00:00
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
}
2016-04-12 07:20:38 +00:00
else if ( section = = conversationSection && ! ( shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION _CONVERSATIONS ) )
2015-12-02 16:18:55 +00:00
{
2015-12-04 08:02:02 +00:00
count = conversationCellDataArray . count ;
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
}
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-11 15:58:59 +00:00
- ( NSString * ) titleForHeaderInSection : ( NSInteger ) section
2015-12-02 16:18:55 +00:00
{
2017-04-11 15:58:59 +00:00
NSString * sectionTitle = nil ;
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 ;
2015-12-02 16:18:55 +00:00
2017-04-11 15:58:59 +00:00
if ( count )
2015-12-02 16:18:55 +00:00
{
2017-04-11 15:58:59 +00:00
sectionTitle = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "room_recents_favourites_section" , @ "Vector" , nil ) , count ] ;
2015-12-02 16:18:55 +00:00
}
2017-04-11 15:58:59 +00:00
else
2015-12-02 16:18:55 +00:00
{
2017-04-11 15:58:59 +00:00
sectionTitle = NSLocalizedStringFromTable ( @ "room_recents_favourites_section_default" , @ "Vector" , nil ) ;
2015-12-02 16:18:55 +00:00
}
2017-04-11 15:58:59 +00:00
}
else if ( section = = conversationSection )
{
count = conversationCellDataArray . count ;
if ( _recentsDataSourceMode = = RecentsDataSourceModePeople )
2017-04-07 12:09:15 +00:00
{
2017-04-11 15:58:59 +00:00
if ( count )
{
sectionTitle = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "people_conversation_section" , @ "Vector" , nil ) , count ] ;
}
else
{
sectionTitle = NSLocalizedStringFromTable ( @ "people_conversation_section_default" , @ "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-04-11 15:58:59 +00:00
if ( count )
{
sectionTitle = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "room_recents_conversations_section" , @ "Vector" , nil ) , count ] ;
}
else
{
sectionTitle = NSLocalizedStringFromTable ( @ "room_recents_conversations_section_default" , @ "Vector" , nil ) ;
}
2015-12-02 16:18:55 +00:00
}
2017-04-11 15:58:59 +00:00
}
else if ( section = = directorySection )
{
sectionTitle = NSLocalizedStringFromTable ( @ "room_recents_directory_section" , @ "Vector" , nil ) ;
}
else if ( section = = lowPrioritySection )
{
count = lowPriorityCellDataArray . count ;
if ( count )
2015-12-09 15:09:46 +00:00
{
2017-04-11 15:58:59 +00:00
sectionTitle = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "room_recents_low_priority_section" , @ "Vector" , nil ) , count ] ;
2015-12-09 15:09:46 +00:00
}
2017-04-11 15:58:59 +00:00
else
{
sectionTitle = NSLocalizedStringFromTable ( @ "room_recents_low_priority_section_default" , @ "Vector" , nil ) ;
}
}
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 )
{
if ( count )
2016-04-12 07:20:38 +00:00
{
2017-04-11 15:58:59 +00:00
sectionTitle = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "people_invites_section" , @ "Vector" , nil ) , count ] ;
2016-04-12 07:20:38 +00:00
}
else
{
2017-04-11 15:58:59 +00:00
sectionTitle = NSLocalizedStringFromTable ( @ "people_invites_section_default" , @ "Vector" , nil ) ;
2016-04-12 07:20:38 +00:00
}
}
2017-04-11 15:58:59 +00:00
else
{
if ( count )
{
sectionTitle = [ NSString stringWithFormat : NSLocalizedStringFromTable ( @ "room_recents_invites_section" , @ "Vector" , nil ) , count ] ;
}
else
{
sectionTitle = NSLocalizedStringFromTable ( @ "room_recents_invites_section_default" , @ "Vector" , nil ) ;
}
}
}
return sectionTitle ;
}
- ( UIView * ) viewForHeaderInSection : ( NSInteger ) section withFrame : ( CGRect ) frame
{
UIView * sectionHeader = [ [ UIView alloc ] initWithFrame : frame ] ;
sectionHeader . backgroundColor = kRiotColorLightGrey ;
NSInteger sectionBitwise = 0 ;
UIImageView * chevronView ;
if ( _areSectionsShrinkable )
{
if ( section = = favoritesSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _FAVORITES ;
}
else if ( section = = conversationSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _CONVERSATIONS ;
}
else if ( section = = directorySection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _CONVERSATIONS ;
}
else if ( section = = lowPrioritySection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _LOWPRIORITY ;
}
else if ( section = = invitesSection )
{
sectionBitwise = RECENTSDATASOURCE_SECTION _INVITES ;
}
}
if ( sectionBitwise )
{
// Add shrink button
UIButton * shrinkButton = [ UIButton buttonWithType : UIButtonTypeCustom ] ;
frame . origin . x = frame . origin . y = 0 ;
shrinkButton . frame = frame ;
shrinkButton . backgroundColor = [ UIColor clearColor ] ;
[ shrinkButton addTarget : self action : @ selector ( onButtonPressed : ) forControlEvents : UIControlEventTouchUpInside ] ;
shrinkButton . tag = sectionBitwise ;
[ sectionHeader addSubview : shrinkButton ] ;
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" ] ;
}
chevronView = [ [ UIImageView alloc ] initWithImage : chevron ] ;
chevronView . contentMode = UIViewContentModeCenter ;
frame = chevronView . frame ;
frame . origin . x = sectionHeader . frame . size . width - frame . size . width - 16 ;
frame . origin . y = ( sectionHeader . frame . size . height - frame . size . height ) / 2 ;
chevronView . frame = frame ;
[ sectionHeader addSubview : chevronView ] ;
chevronView . autoresizingMask = ( UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin ) ;
2016-04-12 07:20:38 +00:00
}
2017-04-11 15:58:59 +00:00
// Add label
frame = sectionHeader . frame ;
frame . origin . x = 20 ;
frame . origin . y = 5 ;
frame . size . width = chevronView ? chevronView . frame . origin . x - 10 : sectionHeader . frame . size . width - 10 ;
frame . size . height - = 10 ;
UILabel * headerLabel = [ [ UILabel alloc ] initWithFrame : frame ] ;
headerLabel . font = [ UIFont boldSystemFontOfSize : 15.0 ] ;
headerLabel . backgroundColor = [ UIColor clearColor ] ;
headerLabel . text = [ self titleForHeaderInSection : section ] ;
[ sectionHeader addSubview : headerLabel ] ;
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-04-07 12:09:15 +00:00
if ( indexPath . section = = directorySection )
{
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
}
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
{
2016-11-30 10:41:20 +00:00
cellData = [ favoriteCellDataArray objectAtIndex : 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 = = 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
{
2016-11-30 10:41:20 +00:00
cellData = [ conversationCellDataArray objectAtIndex : 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
{
2016-11-30 10:41:20 +00:00
cellData = [ lowPriorityCellDataArray objectAtIndex : 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 = = 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
{
2016-11-30 10:41:20 +00:00
cellData = [ invitesCellDataArray objectAtIndex : 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 )
{
return DirectoryRecentTableViewCell . cellHeight ;
}
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
}
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-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 + + )
{
id < MXKRecentCellDataStoring > cellDataStoring = [ cellDataArray objectAtIndex : index ] ;
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 ] ;
}
}
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 ] ;
}
}
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
{
2017-04-06 12:27:45 +00:00
[ invitesCellDataArray removeAllObjects ] ;
[ favoriteCellDataArray removeAllObjects ] ;
[ conversationCellDataArray removeAllObjects ] ;
[ lowPriorityCellDataArray removeAllObjects ] ;
2015-12-03 08:37:45 +00:00
2017-04-06 12:27:45 +00:00
directorySection = favoritesSection = conversationSection = lowPrioritySection = invitesSection = -1 ;
2016-05-30 11:42:45 +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
2015-12-02 16:18:55 +00:00
MXKSessionRecentsDataSource * recentsDataSource = [ displayedRecentsDataSourceArray objectAtIndex : 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-06 12:27:45 +00:00
if ( _recentsDataSourceMode = = RecentsDataSourceModeHome )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
for ( int index = 0 ; index < count ; index + + )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
id < MXKRecentCellDataStoring > recentCellDataStoring = [ recentsDataSource cellDataAtIndex : index ] ;
MXRoom * room = recentCellDataStoring . roomSummary . room ;
if ( room . accountData . tags [ kMXRoomTagFavourite ] )
{
[ 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 ] ;
}
else if ( room . state . membership = = MXMembershipInvite )
{
[ invitesCellDataArray addObject : recentCellDataStoring ] ;
}
else
{
[ conversationCellDataArray addObject : recentCellDataStoring ] ;
2015-12-02 17:10:22 +00:00
}
2015-12-02 16:18:55 +00:00
}
2017-04-06 12:27:45 +00:00
}
else if ( _recentsDataSourceMode = = RecentsDataSourceModeFavourites )
{
for ( int index = 0 ; index < count ; index + + )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
id < MXKRecentCellDataStoring > recentCellDataStoring = [ recentsDataSource cellDataAtIndex : index ] ;
MXRoom * room = recentCellDataStoring . roomSummary . room ;
// 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-06 12:27:45 +00:00
}
else if ( _recentsDataSourceMode = = RecentsDataSourceModePeople )
{
for ( int index = 0 ; index < count ; index + + )
2015-12-09 15:09:46 +00:00
{
2017-04-06 12:27:45 +00:00
id < MXKRecentCellDataStoring > recentCellDataStoring = [ recentsDataSource cellDataAtIndex : index ] ;
MXRoom * room = recentCellDataStoring . roomSummary . room ;
// Keep only the direct rooms .
if ( room . isDirect )
2015-12-09 15:09:46 +00:00
{
2017-04-06 12:27:45 +00:00
if ( room . state . membership = = MXMembershipInvite )
{
[ invitesCellDataArray addObject : recentCellDataStoring ] ;
}
else
{
[ conversationCellDataArray addObject : recentCellDataStoring ] ;
}
2015-12-09 15:09:46 +00:00
}
}
2017-04-06 12:27:45 +00:00
}
else if ( _recentsDataSourceMode = = RecentsDataSourceModeRooms )
{
for ( int index = 0 ; index < count ; index + + )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
id < MXKRecentCellDataStoring > recentCellDataStoring = [ recentsDataSource cellDataAtIndex : index ] ;
MXRoom * room = recentCellDataStoring . roomSummary . room ;
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-04-11 15:58:59 +00:00
// Keep only the invites and the rooms without tag
if ( room . state . membership = = MXMembershipInvite )
{
[ invitesCellDataArray addObject : recentCellDataStoring ] ;
}
else if ( ! room . accountData . tags . count )
{
[ conversationCellDataArray addObject : recentCellDataStoring ] ;
}
2017-04-06 12:27:45 +00:00
}
2015-12-02 16:18:55 +00:00
}
}
2017-04-06 12:27:45 +00:00
2015-12-04 08:02:02 +00:00
if ( favoriteCellDataArray . count > 0 )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
// Sort them according to their tag order
[ favoriteCellDataArray sortUsingComparator : ^ NSComparisonResult ( id < MXKRecentCellDataStoring > recentCellData1 , id < MXKRecentCellDataStoring > recentCellData2 ) {
return [ session compareRoomsByTag : kMXRoomTagFavourite room1 : recentCellData1 . roomSummary . room room2 : recentCellData2 . roomSummary . room ] ;
} ] ;
2015-12-02 16:18:55 +00:00
}
2015-12-04 08:02:02 +00:00
if ( lowPriorityCellDataArray . count > 0 )
2015-12-02 16:18:55 +00:00
{
2017-04-06 12:27:45 +00:00
// Sort them according to their tag order
[ lowPriorityCellDataArray sortUsingComparator : ^ NSComparisonResult ( id < MXKRecentCellDataStoring > recentCellData1 , id < MXKRecentCellDataStoring > recentCellData2 ) {
return [ session compareRoomsByTag : kMXRoomTagLowPriority room1 : recentCellData1 . roomSummary . room room2 : recentCellData2 . roomSummary . room ] ;
} ] ;
2015-12-02 16:18:55 +00:00
}
}
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 ;
}
}
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
2016-11-28 17:03:29 +00:00
- ( BOOL ) tableView : ( UITableView * ) tableView canEditRowAtIndexPath : ( NSIndexPath * ) indexPath
{
// Invited rooms are not editable .
2017-04-06 12:27:45 +00:00
return ( indexPath . section ! = invitesSection ) ;
2016-11-28 17:03:29 +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 ;
}
2015-12-11 10:50:13 +00:00
return ( path && ( ( path . section = = favoritesSection ) || ( path . section = = lowPrioritySection ) || ( path . section = = conversationSection ) ) ) ;
}
- ( 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 ;
}
return nil ;
}
2015-12-15 07:34:46 +00:00
- ( void ) moveRoomCell : ( MXRoom * ) room from : ( NSIndexPath * ) oldPath to : ( NSIndexPath * ) newPath success : ( 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 ] )
{
NSString * oldRoomTag = [ self roomTagAt : oldPath ] ;
NSString * dstRoomTag = [ self roomTagAt : newPath ] ;
2015-12-15 07:34:46 +00:00
NSUInteger oldPos = ( oldPath . section = = newPath . section ) ? oldPath . row : NSNotFound ;
2015-12-11 10:50:13 +00:00
2015-12-15 07:34:46 +00:00
NSString * tagOrder = [ room . mxSession tagOrderToBeAtIndex : newPath . row from : oldPos withTag : dstRoomTag ] ;
2015-12-11 10:50:13 +00:00
2017-03-08 17:54:20 +00:00
NSLog ( @ "[RecentsDataSource] Update the room %@ [%@] tag from %@ to %@ with tag order %@" , room . state . roomId , room . riotDisplayname , oldRoomTag , dstRoomTag , tagOrder ) ;
2015-12-11 10:50:13 +00:00
[ room replaceTag : oldRoomTag
byTag : dstRoomTag
withOrder : tagOrder
success : ^ {
2015-12-11 14:30:26 +00:00
NSLog ( @ "[RecentsDataSource] move is done" ) ;
if ( moveSuccess )
2015-12-11 10:50:13 +00:00
{
2015-12-11 14:30:26 +00:00
moveSuccess ( ) ;
2015-12-11 10:50:13 +00:00
}
2015-12-15 07:34:46 +00:00
// wait the server echo to reload the tableview .
2015-12-14 10:08:57 +00:00
2015-12-11 10:50:13 +00:00
} failure : ^ ( NSError * error ) {
2016-10-21 15:10:02 +00:00
NSLog ( @ "[RecentsDataSource] Failed to update the tag %@ of room (%@)" , dstRoomTag , room . state . roomId ) ;
2015-12-11 14:30:26 +00:00
if ( moveFailure )
{
moveFailure ( error ) ;
}
2015-12-11 10:50:13 +00:00
2017-04-06 12:27:45 +00:00
[ self forceRefresh ] ;
2015-12-14 10:08:57 +00:00
2015-12-11 10:50:13 +00:00
// Notify MatrixKit user
[ [ NSNotificationCenter defaultCenter ] postNotificationName : kMXKErrorNotification object : error ] ;
} ] ;
}
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
}
2015-11-20 17:14:15 +00:00
@ end