diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index caba702b1..bfa659912 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -21,6 +21,10 @@ F02C1A861E8EB04C0045A404 /* PeopleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F02C1A841E8EB04C0045A404 /* PeopleViewController.m */; }; F05BD79E1E7AEBF800C69941 /* UnifiedSearchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F05BD79D1E7AEBF800C69941 /* UnifiedSearchViewController.m */; }; F05BD7A11E7C0E4500C69941 /* MasterTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = F05BD7A01E7C0E4500C69941 /* MasterTabBarController.m */; }; + F075BED61EBB169C00A7B68A /* RoomCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F075BED41EBB169C00A7B68A /* RoomCollectionViewCell.m */; }; + F075BED71EBB169C00A7B68A /* RoomCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F075BED51EBB169C00A7B68A /* RoomCollectionViewCell.xib */; }; + F075BEDB1EBB26F100A7B68A /* TableViewCellWithCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = F075BED91EBB26F100A7B68A /* TableViewCellWithCollectionView.m */; }; + F075BEDC1EBB26F100A7B68A /* TableViewCellWithCollectionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F075BEDA1EBB26F100A7B68A /* TableViewCellWithCollectionView.xib */; }; F083BD1D1E7009ED00A9B29C /* RageShakeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BB0B1E7009EC00A9B29C /* RageShakeManager.m */; }; F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BB0D1E7009EC00A9B29C /* AppDelegate.m */; }; F083BD1F1E7009ED00A9B29C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F083BB0F1E7009EC00A9B29C /* InfoPlist.strings */; }; @@ -475,6 +479,12 @@ F05BD79D1E7AEBF800C69941 /* UnifiedSearchViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UnifiedSearchViewController.m; sourceTree = ""; }; F05BD79F1E7C0E4500C69941 /* MasterTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MasterTabBarController.h; sourceTree = ""; }; F05BD7A01E7C0E4500C69941 /* MasterTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MasterTabBarController.m; sourceTree = ""; }; + F075BED31EBB169C00A7B68A /* RoomCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomCollectionViewCell.h; sourceTree = ""; }; + F075BED41EBB169C00A7B68A /* RoomCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomCollectionViewCell.m; sourceTree = ""; }; + F075BED51EBB169C00A7B68A /* RoomCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomCollectionViewCell.xib; sourceTree = ""; }; + F075BED81EBB26F100A7B68A /* TableViewCellWithCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewCellWithCollectionView.h; sourceTree = ""; }; + F075BED91EBB26F100A7B68A /* TableViewCellWithCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewCellWithCollectionView.m; sourceTree = ""; }; + F075BEDA1EBB26F100A7B68A /* TableViewCellWithCollectionView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableViewCellWithCollectionView.xib; sourceTree = ""; }; F083BB031E7005FD00A9B29C /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F083BB041E7005FD00A9B29C /* RiotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RiotTests.m; sourceTree = ""; }; F083BB0A1E7009EC00A9B29C /* RageShakeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RageShakeManager.h; sourceTree = ""; }; @@ -1752,6 +1762,9 @@ F083BCDC1E7009EC00A9B29C /* RoomList */ = { isa = PBXGroup; children = ( + F075BED31EBB169C00A7B68A /* RoomCollectionViewCell.h */, + F075BED41EBB169C00A7B68A /* RoomCollectionViewCell.m */, + F075BED51EBB169C00A7B68A /* RoomCollectionViewCell.xib */, F083BCDD1E7009EC00A9B29C /* DirectoryRecentTableViewCell.h */, F083BCDE1E7009EC00A9B29C /* DirectoryRecentTableViewCell.m */, F083BCDF1E7009EC00A9B29C /* DirectoryRecentTableViewCell.xib */, @@ -1825,6 +1838,9 @@ F083BD0D1E7009ED00A9B29C /* TableViewCell */ = { isa = PBXGroup; children = ( + F075BED81EBB26F100A7B68A /* TableViewCellWithCollectionView.h */, + F075BED91EBB26F100A7B68A /* TableViewCellWithCollectionView.m */, + F075BEDA1EBB26F100A7B68A /* TableViewCellWithCollectionView.xib */, F083BD0E1E7009ED00A9B29C /* TableViewCellWithButton.h */, F083BD0F1E7009ED00A9B29C /* TableViewCellWithButton.m */, F083BD101E7009ED00A9B29C /* TableViewCellWithButton.xib */, @@ -2011,6 +2027,7 @@ F083BDA61E7009ED00A9B29C /* notifications@3x.png in Resources */, F083BD771E7009ED00A9B29C /* e2e_warning.png in Resources */, F083BDDB1E7009ED00A9B29C /* typing@2x.png in Resources */, + F075BEDC1EBB26F100A7B68A /* TableViewCellWithCollectionView.xib in Resources */, F083BDE71E7009ED00A9B29C /* callend.mp3 in Resources */, F083BD231E7009ED00A9B29C /* add_participant@2x.png in Resources */, F083BDA51E7009ED00A9B29C /* notifications@2x.png in Resources */, @@ -2169,6 +2186,7 @@ F083BD5C1E7009ED00A9B29C /* create_room.png in Resources */, F083BE871E7009ED00A9B29C /* RoomTableViewCell.xib in Resources */, F083BD471E7009ED00A9B29C /* call_video_mute_off_icon@3x.png in Resources */, + F075BED71EBB169C00A7B68A /* RoomCollectionViewCell.xib in Resources */, F083BD941E7009ED00A9B29C /* group@3x.png in Resources */, F083BD591E7009ED00A9B29C /* chevron.png in Resources */, F083BDE11E7009ED00A9B29C /* video_icon@2x.png in Resources */, @@ -2422,6 +2440,7 @@ F083BE191E7009ED00A9B29C /* RecentsViewController.m in Sources */, F083BE351E7009ED00A9B29C /* MediaAlbumTableCell.m in Sources */, F083BE4C1E7009ED00A9B29C /* RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */, + F075BEDB1EBB26F100A7B68A /* TableViewCellWithCollectionView.m in Sources */, F083BE001E7009ED00A9B29C /* FilesSearchCellData.m in Sources */, F083BE7A1E7009ED00A9B29C /* RoomInputToolbarView.m in Sources */, F083BDFF1E7009ED00A9B29C /* RecentsDataSource.m in Sources */, @@ -2461,6 +2480,7 @@ F083BDF91E7009ED00A9B29C /* RoomEmailInvitation.m in Sources */, F083BE341E7009ED00A9B29C /* EncryptionInfoView.m in Sources */, F083BE641E7009ED00A9B29C /* RoomIncomingTextMsgWithoutSenderNameBubbleCell.m in Sources */, + F075BED61EBB169C00A7B68A /* RoomCollectionViewCell.m in Sources */, F0E05A021E963103004B83FB /* FavouritesViewController.m in Sources */, F083BE941E7009ED00A9B29C /* FilesSearchTableViewCell.m in Sources */, F083BE921E7009ED00A9B29C /* SimpleRoomTitleView.m in Sources */, diff --git a/Riot/Model/RoomList/RecentsDataSource.h b/Riot/Model/RoomList/RecentsDataSource.h index 41b87a9fb..1ff9d0b3a 100644 --- a/Riot/Model/RoomList/RecentsDataSource.h +++ b/Riot/Model/RoomList/RecentsDataSource.h @@ -52,6 +52,11 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; @property (nonatomic) NSInteger conversationSection; @property (nonatomic) NSInteger lowPrioritySection; +@property (nonatomic, readonly) NSArray* invitesCellDataArray; +@property (nonatomic, readonly) NSArray* favoriteCellDataArray; +@property (nonatomic, readonly) NSArray* conversationCellDataArray; +@property (nonatomic, readonly) NSArray* lowPriorityCellDataArray; + /** Set the delegate by specifying the selected display mode. */ diff --git a/Riot/Model/RoomList/RecentsDataSource.m b/Riot/Model/RoomList/RecentsDataSource.m index 270613d87..47ab3386f 100644 --- a/Riot/Model/RoomList/RecentsDataSource.m +++ b/Riot/Model/RoomList/RecentsDataSource.m @@ -56,6 +56,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou @implementation RecentsDataSource @synthesize directorySection, invitesSection, favoritesSection, conversationSection, lowPrioritySection; @synthesize hiddenCellIndexPath, droppingCellIndexPath, droppingCellBackGroundView; +@synthesize invitesCellDataArray, favoriteCellDataArray, conversationCellDataArray, lowPriorityCellDataArray; - (instancetype)init { @@ -237,7 +238,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou favoritesSection = sectionsCount++; } - if (conversationCellDataArray.count > 0 || (_recentsDataSourceMode == RecentsDataSourceModePeople) || (_recentsDataSourceMode == RecentsDataSourceModeRooms)) + // Keep visible the main rooms section even if it is empty, except on favourites screen. + if (_recentsDataSourceMode != RecentsDataSourceModeFavourites) { conversationSection = sectionsCount++; } @@ -702,7 +704,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } // Check whether a search session is in progress - if (searchPatternsList) + if (self.searchPatternsList) { tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"search_no_result", @"Vector", nil); } diff --git a/Riot/ViewController/HomeViewController.h b/Riot/ViewController/HomeViewController.h index 0792d0717..a397c2598 100644 --- a/Riot/ViewController/HomeViewController.h +++ b/Riot/ViewController/HomeViewController.h @@ -20,6 +20,6 @@ /** The `HomeViewController` screen is the main app screen. */ -@interface HomeViewController : RecentsViewController +@interface HomeViewController : RecentsViewController @end diff --git a/Riot/ViewController/HomeViewController.m b/Riot/ViewController/HomeViewController.m index b6c8842ca..83aab30d4 100644 --- a/Riot/ViewController/HomeViewController.m +++ b/Riot/ViewController/HomeViewController.m @@ -21,6 +21,15 @@ #import "RecentsDataSource.h" +#import "TableViewCellWithCollectionView.h" +#import "RoomCollectionViewCell.h" + +@interface HomeViewController () +{ + RecentsDataSource *recentsDataSource; +} +@end + @implementation HomeViewController - (void)finalizeInit @@ -37,17 +46,14 @@ self.view.accessibilityIdentifier = @"HomeVCView"; self.recentsTableView.accessibilityIdentifier = @"HomeVCTableView"; - // TODO: Implement the new home screen. - // Hide the table view FTM. - self.recentsTableView.hidden = YES; - UIImageView *sheltieWaiting = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"sheltie-waiting-porch.jpg"]]; - sheltieWaiting.frame = self.view.frame; - sheltieWaiting.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); - sheltieWaiting.contentMode = UIViewContentModeScaleAspectFit; - [self.view addSubview:sheltieWaiting]; - // Add room creation button programmatically [self addRoomCreationButton]; + + // Register table view cell used for rooms collection. + [self.recentsTableView registerClass:TableViewCellWithCollectionView.class forCellReuseIdentifier:TableViewCellWithCollectionView.defaultReuseIdentifier]; + + // Change the table data source. It must be the home view controller itself. + self.recentsTableView.dataSource = self; } - (void)viewWillAppear:(BOOL)animated @@ -56,11 +62,10 @@ [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_home", @"Vector", nil); - if ([self.dataSource isKindOfClass:RecentsDataSource.class]) + if (recentsDataSource) { // Take the lead on the shared data source. - RecentsDataSource *recentsDataSource = (RecentsDataSource*)self.dataSource; - recentsDataSource.areSectionsShrinkable = YES; + recentsDataSource.areSectionsShrinkable = NO; [recentsDataSource setDelegate:self andRecentsDataSourceMode:RecentsDataSourceModeHome]; } } @@ -77,19 +82,30 @@ #pragma mark - Override RecentsViewController +- (void)displayList:(MXKRecentsDataSource *)listDataSource +{ + [super displayList:listDataSource]; + + // Change the table data source. It must be the home view controller itself. + self.recentsTableView.dataSource = self; + + // Keep a ref on the recents data source + if ([listDataSource isKindOfClass:RecentsDataSource.class]) + { + recentsDataSource = (RecentsDataSource*)listDataSource; + } +} + - (void)refreshCurrentSelectedCell:(BOOL)forceVisible { // Check whether the recents data source is correctly configured. - if ([self.dataSource isKindOfClass:RecentsDataSource.class]) + if (recentsDataSource.recentsDataSourceMode != RecentsDataSourceModeHome) { - RecentsDataSource *recentsDataSource = (RecentsDataSource*)self.dataSource; - if (recentsDataSource.recentsDataSourceMode != RecentsDataSourceModeHome) - { - return; - } + return; } - [super refreshCurrentSelectedCell:forceVisible]; + // TODO: refreshCurrentSelectedCell + //[super refreshCurrentSelectedCell:forceVisible]; } - (void)onRoomCreationButtonPressed @@ -136,4 +152,141 @@ [currentAlert showInViewController:self]; } +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + // Return the actual number of sections prepared in recents dataSource. + return [recentsDataSource numberOfSectionsInTableView:tableView]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + // Each rooms section is represented by only one collection view. + return 1; +} + +- (CGFloat)heightForHeaderInSection:(NSInteger)section +{ + // Keep the recents data source informations on the section headers. + return [recentsDataSource heightForHeaderInSection:section]; +} + +- (NSString *)titleForHeaderInSection:(NSInteger)section +{ + // Keep the recents data source informations on the section headers. + return [recentsDataSource titleForHeaderInSection:section]; +} + +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +{ + // Keep the recents data source informations on the section headers. + return [recentsDataSource viewForHeaderInSection:section withFrame:frame]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.section == recentsDataSource.conversationSection && !recentsDataSource.conversationCellDataArray.count) + { + MXKTableViewCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCell defaultReuseIdentifier]]; + if (!tableViewCell) + { + tableViewCell = [[MXKTableViewCell alloc] init]; + tableViewCell.textLabel.textColor = kRiotTextColorGray; + tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; + tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; + } + + // Check whether a search session is in progress + if (recentsDataSource.searchPatternsList) + { + tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"search_no_result", @"Vector", nil); + } + else + { + tableViewCell.textLabel.text = NSLocalizedStringFromTable(@"room_recents_no_conversation", @"Vector", nil); + } + + return tableViewCell; + } + + TableViewCellWithCollectionView *collectionViewCell = [tableView dequeueReusableCellWithIdentifier:TableViewCellWithCollectionView.defaultReuseIdentifier forIndexPath:indexPath]; + collectionViewCell.collectionView.tag = indexPath.section; + [collectionViewCell.collectionView registerClass:RoomCollectionViewCell.class forCellWithReuseIdentifier:RoomCollectionViewCell.defaultReuseIdentifier]; + collectionViewCell.collectionView.delegate = self; + collectionViewCell.collectionView.dataSource = self; + collectionViewCell.selectionStyle = UITableViewCellSelectionStyleNone; + + return collectionViewCell; +} + +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ + return NO; +} + +#pragma mark - UITableView delegate + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.section == recentsDataSource.conversationSection && !recentsDataSource.conversationCellDataArray.count) + { + return 50.0; + } + + // Return the fixed height of the collection view cell used to display a room. + return [RoomCollectionViewCell defaultCellSize].height; +} + +#pragma mark - UICollectionViewDataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +{ + return [recentsDataSource tableView:self.recentsTableView numberOfRowsInSection:collectionView.tag]; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath +{ + RoomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:RoomCollectionViewCell.defaultReuseIdentifier + forIndexPath:indexPath]; + + id cellData = [recentsDataSource cellDataAtIndexPath:[NSIndexPath indexPathForRow:indexPath.item inSection:collectionView.tag]]; + + if (cellData) + { + [cell render:cellData]; + cell.tag = indexPath.item; + + //TODO: add long tap gesture recognizer. +// UILongPressGestureRecognizer *cellLongPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onCollectionViewCellLongPress:)]; +// [cell addGestureRecognizer:cellLongPressGesture]; + } + + return cell; +} + +#pragma mark - UICollectionViewDelegate + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath +{ + if (self.delegate) + { + id cellData = [recentsDataSource cellDataAtIndexPath:[NSIndexPath indexPathForRow:indexPath.item inSection:collectionView.tag]]; + + [self.delegate recentListViewController:self didSelectRoom:cellData.roomSummary.roomId inMatrixSession:cellData.roomSummary.room.mxSession]; + } + + // Hide the keyboard when user select a room + // do not hide the searchBar until the view controller disappear + // on tablets / iphone 6+, the user could expect to search again while looking at a room + [self.recentsSearchBar resignFirstResponder]; +} + +#pragma mark - UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath +{ + return [RoomCollectionViewCell defaultCellSize]; +} + @end diff --git a/Riot/ViewController/RecentsViewController.h b/Riot/ViewController/RecentsViewController.h index 38095dc71..d02c0c011 100644 --- a/Riot/ViewController/RecentsViewController.h +++ b/Riot/ViewController/RecentsViewController.h @@ -53,6 +53,12 @@ */ @property (nonatomic) BOOL shouldScrollToTopOnRefresh; +/** + Tell whether the drag and drop option are enabled. NO by default. + This option is used to move a room from a section to another. + */ +@property (nonatomic) BOOL enableDragging; + /** Tell whether the sticky headers are enabled. NO by default. */ diff --git a/Riot/ViewController/RecentsViewController.m b/Riot/ViewController/RecentsViewController.m index 4c37e9c5e..3633a01ac 100644 --- a/Riot/ViewController/RecentsViewController.m +++ b/Riot/ViewController/RecentsViewController.m @@ -41,7 +41,8 @@ // Tell whether a recents refresh is pending (suspended during editing mode). BOOL isRefreshPending; - // recents drag and drop management + // Recents drag and drop management + UILongPressGestureRecognizer *longPressGestureRecognizer; UIImageView *cellSnapshot; NSIndexPath* movingCellPath; MXRoom* movingRoom; @@ -95,6 +96,8 @@ // Set default screen name _screenName = @"RecentsScreen"; + _enableDragging = NO; + _enableStickyHeaders = NO; _stickyHeaderHeight = 30.0; @@ -128,9 +131,6 @@ // Register here the customized cell view class used to render recents [self.recentsTableView registerNib:RecentTableViewCell.nib forCellReuseIdentifier:RecentTableViewCell.defaultReuseIdentifier]; [self.recentsTableView registerNib:InviteRecentTableViewCell.nib forCellReuseIdentifier:InviteRecentTableViewCell.defaultReuseIdentifier]; - - UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onRecentsLongPress:)]; - [self.recentsTableView addGestureRecognizer:longPress]; // Hide line separators of empty cells self.recentsTableView.tableFooterView = [[UIView alloc] init]; @@ -150,6 +150,8 @@ - (void)destroy { [super destroy]; + + longPressGestureRecognizer = nil; if (currentRequest) { @@ -1238,7 +1240,25 @@ } } -#pragma mark - recents drag & drop management +#pragma mark - Recents drag & drop management + +- (void)setEnableDragging:(BOOL)enableDragging +{ + if (_enableDragging != enableDragging) + { + _enableDragging = enableDragging; + + if (_enableDragging) + { + longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onRecentsLongPress:)]; + [self.recentsTableView addGestureRecognizer:longPressGestureRecognizer]; + } + else if (longPressGestureRecognizer) + { + [self.recentsTableView removeGestureRecognizer:longPressGestureRecognizer]; + } + } +} - (void)onRecentsDragEnd { @@ -1256,6 +1276,11 @@ - (IBAction)onRecentsLongPress:(id)sender { + if (sender != longPressGestureRecognizer) + { + return; + } + RecentsDataSource* recentsDataSource = nil; if ([self.dataSource isKindOfClass:[RecentsDataSource class]]) @@ -1269,8 +1294,7 @@ return; } - UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender; - UIGestureRecognizerState state = longPress.state; + UIGestureRecognizerState state = longPressGestureRecognizer.state; // check if there is a moving cell during the long press managemnt if ((state != UIGestureRecognizerStateBegan) && !movingCellPath) @@ -1278,7 +1302,7 @@ return; } - CGPoint location = [longPress locationInView:self.recentsTableView]; + CGPoint location = [longPressGestureRecognizer locationInView:self.recentsTableView]; switch (state) { diff --git a/Riot/Views/RoomList/RoomCollectionViewCell.h b/Riot/Views/RoomList/RoomCollectionViewCell.h new file mode 100644 index 000000000..c69d1e5b3 --- /dev/null +++ b/Riot/Views/RoomList/RoomCollectionViewCell.h @@ -0,0 +1,46 @@ +/* + Copyright 2017 Vector Creations Ltd + + 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 + +/** + 'RoomCollectionViewCell' class is used to display a room in a collection view. + */ +@interface RoomCollectionViewCell : MXKCollectionViewCell +{ +@protected + /** + The current cell data displayed by the collection view cell + */ + id roomCellData; +} + +@property (weak, nonatomic) IBOutlet UILabel *roomTitle; + +@property (weak, nonatomic) IBOutlet UIView *directRoomBorderView; +@property (weak, nonatomic) IBOutlet MXKImageView *roomAvatar; +@property (weak, nonatomic) IBOutlet UIImageView *encryptedRoomIcon; + +@property (weak, nonatomic) IBOutlet UILabel *missedNotifAndUnreadBadgeLabel; +@property (weak, nonatomic) IBOutlet UIView *missedNotifAndUnreadBadgeBgView; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *missedNotifAndUnreadBadgeBgViewWidthConstraint; + +/** + The default collection view cell size. + */ ++ (CGSize)defaultCellSize; + +@end diff --git a/Riot/Views/RoomList/RoomCollectionViewCell.m b/Riot/Views/RoomList/RoomCollectionViewCell.m new file mode 100644 index 000000000..48e855b1a --- /dev/null +++ b/Riot/Views/RoomList/RoomCollectionViewCell.m @@ -0,0 +1,141 @@ +/* + Copyright 2017 Vector Creations Ltd + + 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 "RoomCollectionViewCell.h" + +#import "AvatarGenerator.h" + +#import "RiotDesignValues.h" + +#import "MXRoom+Riot.h" + +@implementation RoomCollectionViewCell + +#pragma mark - Class methods + +- (void)awakeFromNib +{ + [super awakeFromNib]; + + // Initialize unread count badge + [_missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10]; + _missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = 0; + + self.roomTitle.textColor = kRiotTextColorBlack; + self.missedNotifAndUnreadBadgeLabel.textColor = [UIColor whiteColor]; + + self.directRoomBorderView.backgroundColor = kRiotColorGreen; + self.directRoomBorderView.alpha = 0.75; + [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; + self.directRoomBorderView.clipsToBounds = YES; + + // Disable the user interaction on the room avatar. + self.roomAvatar.userInteractionEnabled = NO; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + // Round image view + [_roomAvatar.layer setCornerRadius:_roomAvatar.frame.size.width / 2]; + _roomAvatar.clipsToBounds = YES; +} + +- (void)render:(MXKCellData *)cellData +{ + // Hide by default missed notifications and unread widgets + self.missedNotifAndUnreadBadgeBgView.hidden = YES; + self.missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = 0; + + roomCellData = (id)cellData; + if (roomCellData) + { + // Report computed values as is + self.roomTitle.text = roomCellData.roomDisplayname; + + // Notify unreads and bing + if (roomCellData.hasUnread) + { + if (0 < roomCellData.notificationCount) + { + self.missedNotifAndUnreadBadgeBgView.hidden = NO; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? kRiotColorPinkRed : kRiotColorGreen; + + self.missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", roomCellData.notificationCount]; + [self.missedNotifAndUnreadBadgeLabel sizeToFit]; + + self.missedNotifAndUnreadBadgeBgViewWidthConstraint.constant = self.missedNotifAndUnreadBadgeLabel.frame.size.width + 18; + } + + // Use bold font for the room title + if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) + { + self.roomTitle.font = [UIFont systemFontOfSize:15 weight:UIFontWeightBold]; + } + else + { + self.roomTitle.font = [UIFont boldSystemFontOfSize:15]; + } + } + else + { + // The room title is not bold anymore + if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) + { + self.roomTitle.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; + } + else + { + self.roomTitle.font = [UIFont systemFontOfSize:15]; + } + } + + self.roomAvatar.backgroundColor = [UIColor clearColor]; + + self.directRoomBorderView.hidden = !roomCellData.roomSummary.room.isDirect; + + self.encryptedRoomIcon.hidden = !roomCellData.roomSummary.isEncrypted; + + [roomCellData.roomSummary.room setRoomAvatarImageIn:self.roomAvatar]; + } +} + ++ (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth +{ + // The height is fixed + return 110; +} + ++ (CGSize)defaultCellSize +{ + return CGSizeMake(90, 110); +} + +- (void)prepareForReuse +{ + [super prepareForReuse]; + + // Remove all gesture recognizers + while (self.gestureRecognizers.count) + { + [self removeGestureRecognizer:self.gestureRecognizers[0]]; + } + self.tag = -1; +} + +@end + diff --git a/Riot/Views/RoomList/RoomCollectionViewCell.xib b/Riot/Views/RoomList/RoomCollectionViewCell.xib new file mode 100644 index 000000000..275dbe6e1 --- /dev/null +++ b/Riot/Views/RoomList/RoomCollectionViewCell.xib @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Views/TableViewCell/TableViewCellWithCollectionView.h b/Riot/Views/TableViewCell/TableViewCellWithCollectionView.h new file mode 100644 index 000000000..d44894c2b --- /dev/null +++ b/Riot/Views/TableViewCell/TableViewCellWithCollectionView.h @@ -0,0 +1,23 @@ +/* + Copyright 2017 Vector Creations Ltd + + 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 + +@interface TableViewCellWithCollectionView : MXKTableViewCell + +@property (strong, nonatomic) IBOutlet UICollectionView *collectionView; + +@end diff --git a/Riot/Views/TableViewCell/TableViewCellWithCollectionView.m b/Riot/Views/TableViewCell/TableViewCellWithCollectionView.m new file mode 100644 index 000000000..85cab101b --- /dev/null +++ b/Riot/Views/TableViewCell/TableViewCellWithCollectionView.m @@ -0,0 +1,31 @@ +/* + Copyright 2017 Vector Creations Ltd + + 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 "TableViewCellWithCollectionView.h" + +@implementation TableViewCellWithCollectionView + +- (void)prepareForReuse +{ + [super prepareForReuse]; + + self.collectionView.tag = -1; + self.collectionView.dataSource = nil; + self.collectionView.delegate = nil; +} + +@end + diff --git a/Riot/Views/TableViewCell/TableViewCellWithCollectionView.xib b/Riot/Views/TableViewCell/TableViewCellWithCollectionView.xib new file mode 100644 index 000000000..46ff0317f --- /dev/null +++ b/Riot/Views/TableViewCell/TableViewCellWithCollectionView.xib @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +