diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index c767c6dd37..ad472c8325 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -422,6 +422,9 @@ F083BEA21E7009ED00A9B29C /* TableViewCellWithPhoneNumberTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BD1B1E7009ED00A9B29C /* TableViewCellWithPhoneNumberTextField.m */; }; F083BEA31E7009ED00A9B29C /* TableViewCellWithPhoneNumberTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = F083BD1C1E7009ED00A9B29C /* TableViewCellWithPhoneNumberTextField.xib */; }; F083BEA51E70356E00A9B29C /* RiotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BB041E7005FD00A9B29C /* RiotTests.m */; }; + F0A4A1671EF7CB66003630DB /* members_list_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = F0A4A1641EF7CB66003630DB /* members_list_icon.png */; }; + F0A4A1681EF7CB66003630DB /* members_list_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F0A4A1651EF7CB66003630DB /* members_list_icon@2x.png */; }; + F0A4A1691EF7CB66003630DB /* members_list_icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F0A4A1661EF7CB66003630DB /* members_list_icon@3x.png */; }; F0D869EB1EC455A100BB0A2B /* create_direct_chat.png in Resources */ = {isa = PBXBuildFile; fileRef = F0D869E81EC455A100BB0A2B /* create_direct_chat.png */; }; F0D869EC1EC455A100BB0A2B /* create_direct_chat@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F0D869E91EC455A100BB0A2B /* create_direct_chat@2x.png */; }; F0D869ED1EC455A100BB0A2B /* create_direct_chat@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F0D869EA1EC455A100BB0A2B /* create_direct_chat@3x.png */; }; @@ -1006,6 +1009,9 @@ F083BD1C1E7009ED00A9B29C /* TableViewCellWithPhoneNumberTextField.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableViewCellWithPhoneNumberTextField.xib; sourceTree = ""; }; F094A9A21B78D8F000B1FBBF /* Riot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Riot.app; sourceTree = BUILT_PRODUCTS_DIR; }; F094A9BE1B78D8F000B1FBBF /* RiotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RiotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + F0A4A1641EF7CB66003630DB /* members_list_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = members_list_icon.png; sourceTree = ""; }; + F0A4A1651EF7CB66003630DB /* members_list_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "members_list_icon@2x.png"; sourceTree = ""; }; + F0A4A1661EF7CB66003630DB /* members_list_icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "members_list_icon@3x.png"; sourceTree = ""; }; F0D869E81EC455A100BB0A2B /* create_direct_chat.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = create_direct_chat.png; sourceTree = ""; }; F0D869E91EC455A100BB0A2B /* create_direct_chat@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "create_direct_chat@2x.png"; sourceTree = ""; }; F0D869EA1EC455A100BB0A2B /* create_direct_chat@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "create_direct_chat@3x.png"; sourceTree = ""; }; @@ -1156,6 +1162,9 @@ F083BB151E7009EC00A9B29C /* Images */ = { isa = PBXGroup; children = ( + F0A4A1641EF7CB66003630DB /* members_list_icon.png */, + F0A4A1651EF7CB66003630DB /* members_list_icon@2x.png */, + F0A4A1661EF7CB66003630DB /* members_list_icon@3x.png */, F0614A101EDEE65000F5DC9A /* cancel.png */, F0614A111EDEE65000F5DC9A /* cancel@2x.png */, F0614A121EDEE65000F5DC9A /* cancel@3x.png */, @@ -2130,6 +2139,7 @@ F083BD891E7009ED00A9B29C /* file_music_icon.png in Resources */, F083BDD11E7009ED00A9B29C /* settings_icon.png in Resources */, F083BD811E7009ED00A9B29C /* favourite@2x.png in Resources */, + F0A4A1681EF7CB66003630DB /* members_list_icon@2x.png in Resources */, F083BD9F1E7009ED00A9B29C /* mod_icon@2x.png in Resources */, F083BD801E7009ED00A9B29C /* favourite.png in Resources */, F083BD4B1E7009ED00A9B29C /* camera_capture.png in Resources */, @@ -2266,6 +2276,7 @@ F083BD631E7009ED00A9B29C /* direct_icon@2x.png in Resources */, F083BE991E7009ED00A9B29C /* MessagesSearchResultTextMsgBubbleCell.xib in Resources */, F083BD711E7009ED00A9B29C /* e2e_unencrypted.png in Resources */, + F0A4A1671EF7CB66003630DB /* members_list_icon.png in Resources */, F083BE731E7009ED00A9B29C /* RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib in Resources */, F083BD251E7009ED00A9B29C /* admin_icon.png in Resources */, F083BDBE1E7009ED00A9B29C /* riot_icon@3x.png in Resources */, @@ -2328,6 +2339,7 @@ F083BDE01E7009ED00A9B29C /* video_icon.png in Resources */, F083BD601E7009ED00A9B29C /* details_icon@2x.png in Resources */, F083BE5F1E7009ED00A9B29C /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib in Resources */, + F0A4A1691EF7CB66003630DB /* members_list_icon@3x.png in Resources */, F083BE8D1E7009ED00A9B29C /* PreviewRoomTitleView.xib in Resources */, F083BD561E7009ED00A9B29C /* camera_video_capture.png in Resources */, F083BD651E7009ED00A9B29C /* directChatOff.png in Resources */, diff --git a/Riot/Assets/Images/members_list_icon.png b/Riot/Assets/Images/members_list_icon.png new file mode 100644 index 0000000000..eb23ecd653 Binary files /dev/null and b/Riot/Assets/Images/members_list_icon.png differ diff --git a/Riot/Assets/Images/members_list_icon@2x.png b/Riot/Assets/Images/members_list_icon@2x.png new file mode 100644 index 0000000000..8eb7a46cab Binary files /dev/null and b/Riot/Assets/Images/members_list_icon@2x.png differ diff --git a/Riot/Assets/Images/members_list_icon@3x.png b/Riot/Assets/Images/members_list_icon@3x.png new file mode 100644 index 0000000000..ec24ed814d Binary files /dev/null and b/Riot/Assets/Images/members_list_icon@3x.png differ diff --git a/Riot/Base.lproj/Main.storyboard b/Riot/Base.lproj/Main.storyboard index d4a2d46410..abe2006502 100644 --- a/Riot/Base.lproj/Main.storyboard +++ b/Riot/Base.lproj/Main.storyboard @@ -45,6 +45,7 @@ + @@ -524,6 +525,24 @@ + + + + + + + + + + + + + + + + + + @@ -558,9 +577,9 @@ - + + - - + diff --git a/Riot/ViewController/RoomParticipantsViewController.m b/Riot/ViewController/RoomParticipantsViewController.m index 0fd839f48e..9f762fbd00 100644 --- a/Riot/ViewController/RoomParticipantsViewController.m +++ b/Riot/ViewController/RoomParticipantsViewController.m @@ -601,7 +601,7 @@ - (void)onAddParticipantButtonPressed // Add a plus icon to the contact cell in the contacts picker, in order to make it more understandable for the end user. contactsDataSource.contactCellAccessoryImage = [UIImage imageNamed:@"plus_icon"]; - // List all the participants by their matrix user id, or a room 3pid invite token to ignore them during the contacts search. + // List all the participants matrix user id to ignore them during the contacts search. for (Contact *contact in actualParticipants) { [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxMember.userId]; @@ -612,10 +612,6 @@ - (void)onAddParticipantButtonPressed { [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxMember.userId]; } - else if (contact.mxThirdPartyInvite) - { - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxThirdPartyInvite.token]; - } } if (userParticipant) { @@ -905,7 +901,7 @@ - (void)removePendingActionMask - (void)pushViewController:(UIViewController*)viewController { // Check whether the view controller is displayed inside a segmented one. - if (self.parentViewController) + if (self.parentViewController.navigationController) { // Hide back button title self.parentViewController.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; diff --git a/Riot/ViewController/RoomViewController.h b/Riot/ViewController/RoomViewController.h index 45fd0f0bd1..ac4c2ac11f 100644 --- a/Riot/ViewController/RoomViewController.h +++ b/Riot/ViewController/RoomViewController.h @@ -23,9 +23,11 @@ #import "RoomParticipantsViewController.h" +#import "ContactsTableViewController.h" + #import "UIViewController+RiotSearch.h" -@interface RoomViewController : MXKRoomViewController +@interface RoomViewController : MXKRoomViewController // The expanded header @property (weak, nonatomic) IBOutlet UIView *expandedHeaderContainer; diff --git a/Riot/ViewController/RoomViewController.m b/Riot/ViewController/RoomViewController.m index 001c888b13..77460e2c07 100644 --- a/Riot/ViewController/RoomViewController.m +++ b/Riot/ViewController/RoomViewController.m @@ -906,7 +906,7 @@ - (BOOL)isIRCStyleCommand:(NSString*)string } failure:^(NSError *error) { - NSLog(@"[Vector RoomVC] Join roomAlias (%@) failed", roomAlias); + NSLog(@"[RoomVC] Join roomAlias (%@) failed", roomAlias); //Alert user [[AppDelegate theDelegate] showErrorAsAlert:error]; @@ -1007,7 +1007,7 @@ - (void)destroy if (previewHeader || (self.expandedHeaderContainer.isHidden == NO)) { // Here [destroy] is called before [viewWillDisappear:] - NSLog(@"[Vector RoomVC] destroyed whereas it is still visible"); + NSLog(@"[RoomVC] destroyed whereas it is still visible"); [previewHeader removeFromSuperview]; previewHeader = nil; @@ -1198,7 +1198,7 @@ - (void)showExpandedHeader:(BOOL)isVisible // - if the event details view is displayed if (isVisible && (isSizeTransitionInProgress == YES || !self.roomDataSource || !self.roomDataSource.isLive || (self.roomDataSource.room.state.membership != MXMembershipJoin) || !self.splitViewController || encryptionInfoView.superview || eventDetailsView.superview)) { - NSLog(@"[Vector RoomVC] Show expanded header ignored"); + NSLog(@"[RoomVC] Show expanded header ignored"); return; } @@ -1279,7 +1279,7 @@ - (void)showPreviewHeader:(BOOL)isVisible // or if the view controller is not embedded inside a split view controller yet. if (isVisible && (isSizeTransitionInProgress == YES || !self.splitViewController)) { - NSLog(@"[Vector RoomVC] Show preview header ignored"); + NSLog(@"[RoomVC] Show preview header ignored"); return; } @@ -1984,7 +1984,7 @@ - (void)showEditButtonAlertMenuForEvent:(MXEvent*)selectedEvent inCell:(idcurrentAlert = nil; + + }]; + + [currentAlert addActionWithTitle:NSLocalizedStringFromTable(@"invite", @"Vector", nil) + style:MXKAlertActionStyleDefault + handler:^(MXKAlert *alert) { + + __strong __typeof(weakSelf)strongSelf = weakSelf; + strongSelf->currentAlert = nil; + + MXSession* session = strongSelf.roomDataSource.mxSession; + NSString* roomId = strongSelf.roomDataSource.roomId; + MXRoom *room = [session roomWithRoomId:roomId]; + + NSArray *identifiers = contact.matrixIdentifiers; + NSString *participantId; + + if (identifiers.count) + { + participantId = identifiers.firstObject; + + // Invite this user if a room is defined + [room inviteUser:participantId success:^{ + + // Refresh display by removing the contacts picker + [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + NSLog(@"[RoomVC] Invite %@ failed", participantId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; + } + else + { + if (contact.emailAddresses.count) + { + // This is a local contact, consider the first email by default. + // TODO: Prompt the user to select the right email. + MXKEmail *email = contact.emailAddresses.firstObject; + participantId = email.emailAddress; + } + else + { + // This is the text filled by the user. + participantId = contact.displayName; + } + + // Is it an email or a Matrix user ID? + if ([MXTools isEmailAddress:participantId]) + { + [room inviteUserByEmail:participantId success:^{ + + // Refresh display by removing the contacts picker + [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + NSLog(@"[RoomVC] Invite be email %@ failed", participantId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; + } + else //if ([MXTools isMatrixUserIdentifier:participantId]) + { + [room inviteUser:participantId success:^{ + + // Refresh display by removing the contacts picker + [contactsTableViewController withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + NSLog(@"[RoomVC] Invite %@ failed", participantId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; + } + } + + }]; + + currentAlert.mxkAccessibilityIdentifier = @"RoomVCInviteAlert"; + [currentAlert showInViewController:self]; +} + @end diff --git a/Riot/Views/RoomTitle/ExpandedRoomTitleView.xib b/Riot/Views/RoomTitle/ExpandedRoomTitleView.xib index 200d52f666..78005181b8 100644 --- a/Riot/Views/RoomTitle/ExpandedRoomTitleView.xib +++ b/Riot/Views/RoomTitle/ExpandedRoomTitleView.xib @@ -1,11 +1,12 @@ - - + + - + + @@ -47,12 +48,12 @@ - - + + - - + + @@ -67,9 +68,28 @@ - + + + + + + + + + + + + + + + + + + + + @@ -77,15 +97,18 @@ + - + + - + + @@ -97,16 +120,17 @@ + - + @@ -119,6 +143,7 @@ - + + diff --git a/Riot/Views/RoomTitle/RoomTitleView.h b/Riot/Views/RoomTitle/RoomTitleView.h index 36d9ee86f2..23b198f5ec 100644 --- a/Riot/Views/RoomTitle/RoomTitleView.h +++ b/Riot/Views/RoomTitle/RoomTitleView.h @@ -36,6 +36,7 @@ @property (weak, nonatomic) IBOutlet UIView *titleMask; @property (weak, nonatomic) IBOutlet UIView *roomDetailsMask; +@property (weak, nonatomic) IBOutlet UIView *addParticipantMask; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *displayNameCenterXConstraint; @property (weak, nonatomic) IBOutlet UIImageView *roomDetailsIconImageView; @@ -54,4 +55,4 @@ */ - (void)reportTapGesture:(UITapGestureRecognizer*)tapGestureRecognizer; -@end \ No newline at end of file +@end diff --git a/Riot/Views/RoomTitle/RoomTitleView.m b/Riot/Views/RoomTitle/RoomTitleView.m index cbe4b02787..2240da8e59 100644 --- a/Riot/Views/RoomTitle/RoomTitleView.m +++ b/Riot/Views/RoomTitle/RoomTitleView.m @@ -59,6 +59,16 @@ - (void)awakeFromNib [self.roomDetailsMask addGestureRecognizer:tap]; self.roomDetailsMask.userInteractionEnabled = YES; } + + if (_addParticipantMask) + { + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(reportTapGesture:)]; + [tap setNumberOfTouchesRequired:1]; + [tap setNumberOfTapsRequired:1]; + [tap setDelegate:self]; + [self.addParticipantMask addGestureRecognizer:tap]; + self.addParticipantMask.userInteractionEnabled = YES; + } } - (void)layoutSubviews