Skip to content

Commit

Permalink
Feature - Improve the people invite screens
Browse files Browse the repository at this point in the history
#904.

+"Add contact" button should be added on Room Member list #905
  • Loading branch information
giomfo committed Jan 13, 2017
1 parent 8efbbdf commit c03638a
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 52 deletions.
12 changes: 12 additions & 0 deletions Vector.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@
F03DE2A51D0EFA6A00E8B65C /* AttachmentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03DE2A41D0EFA6A00E8B65C /* AttachmentsViewController.m */; };
F046528D1E250B0A00EA4E77 /* ContactsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F046528C1E250B0A00EA4E77 /* ContactsTableViewController.m */; };
F046528F1E28439E00EA4E77 /* ContactsTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F046528E1E28439E00EA4E77 /* ContactsTableViewController.xib */; };
F04652931E28E0E300EA4E77 /* add_participant.png in Resources */ = {isa = PBXBuildFile; fileRef = F04652901E28E0E300EA4E77 /* add_participant.png */; };
F04652941E28E0E300EA4E77 /* add_participant@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F04652911E28E0E300EA4E77 /* add_participant@2x.png */; };
F04652951E28E0E300EA4E77 /* add_participant@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = F04652921E28E0E300EA4E77 /* add_participant@3x.png */; };
F047DBB51C576F2200952DA2 /* AuthenticationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F047DBB41C576F2200952DA2 /* AuthenticationViewController.xib */; };
F047DBB91C576F6600952DA2 /* AuthInputsView.m in Sources */ = {isa = PBXBuildFile; fileRef = F047DBB71C576F6600952DA2 /* AuthInputsView.m */; };
F047DBBA1C576F6600952DA2 /* AuthInputsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F047DBB81C576F6600952DA2 /* AuthInputsView.xib */; };
Expand Down Expand Up @@ -644,6 +647,9 @@
F046528B1E250B0A00EA4E77 /* ContactsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsTableViewController.h; sourceTree = "<group>"; };
F046528C1E250B0A00EA4E77 /* ContactsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsTableViewController.m; sourceTree = "<group>"; };
F046528E1E28439E00EA4E77 /* ContactsTableViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContactsTableViewController.xib; sourceTree = "<group>"; };
F04652901E28E0E300EA4E77 /* add_participant.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = add_participant.png; sourceTree = "<group>"; };
F04652911E28E0E300EA4E77 /* add_participant@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add_participant@2x.png"; sourceTree = "<group>"; };
F04652921E28E0E300EA4E77 /* add_participant@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add_participant@3x.png"; sourceTree = "<group>"; };
F047DBB41C576F2200952DA2 /* AuthenticationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AuthenticationViewController.xib; sourceTree = "<group>"; };
F047DBB61C576F6600952DA2 /* AuthInputsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthInputsView.h; sourceTree = "<group>"; };
F047DBB71C576F6600952DA2 /* AuthInputsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthInputsView.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1144,6 +1150,9 @@
F03BF5B41D8BF5B1002EF6A7 /* Images */ = {
isa = PBXGroup;
children = (
F04652901E28E0E300EA4E77 /* add_participant.png */,
F04652911E28E0E300EA4E77 /* add_participant@2x.png */,
F04652921E28E0E300EA4E77 /* add_participant@3x.png */,
F04ACE001E154C540000B970 /* riot_icon.png */,
F04ACE011E154C540000B970 /* riot_icon@2x.png */,
F04ACE021E154C540000B970 /* riot_icon@3x.png */,
Expand Down Expand Up @@ -1793,6 +1802,7 @@
files = (
F0D2D9881C197DCB007B8C96 /* RoomIncomingTextMsgBubbleCell.xib in Resources */,
F03BF6CB1D8BF5B1002EF6A7 /* settings_icon.png in Resources */,
F04652931E28E0E300EA4E77 /* add_participant.png in Resources */,
F03BF6791D8BF5B1002EF6A7 /* chevron@3x.png in Resources */,
F03BF64B1D8BF5B1002EF6A7 /* admin_icon@3x.png in Resources */,
F09EAFB61DD2109B009C7EFB /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib in Resources */,
Expand Down Expand Up @@ -1828,6 +1838,7 @@
7165A25C1C05CD42003635D7 /* SegmentedViewController.xib in Resources */,
F03BF65F1D8BF5B1002EF6A7 /* call_speaker_off_icon@2x.png in Resources */,
F0A4B2F11E0073A30072D355 /* animatedLogo-1.png in Resources */,
F04652941E28E0E300EA4E77 /* add_participant@2x.png in Resources */,
F03BF6B41D8BF5B1002EF6A7 /* priorityLow@2x.png in Resources */,
F08294691DB503FE00CEAB63 /* direct_icon@2x.png in Resources */,
F04ACE041E154C540000B970 /* riot_icon@2x.png in Resources */,
Expand Down Expand Up @@ -1889,6 +1900,7 @@
F0BE3DF21C6CE28300AC3111 /* RoomMemberDetailsViewController.xib in Resources */,
F09EAF9C1DD2109B009C7EFB /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib in Resources */,
F023A0161D9034FE00C517FB /* call_video_mute_on_icon.png in Resources */,
F04652951E28E0E300EA4E77 /* add_participant@3x.png in Resources */,
F03BF66A1D8BF5B1002EF6A7 /* camera_capture.png in Resources */,
F0AF11F61D1029CF00FEE52F /* RoomIdOrAliasTableViewCell.xib in Resources */,
F08714CC1DB9EFEE0075F633 /* directChatOff@3x.png in Resources */,
Expand Down
Binary file added Vector/Assets/Images/add_participant.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Vector/Assets/Images/add_participant@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Vector/Assets/Images/add_participant@3x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions Vector/Assets/en.lproj/Vector.strings
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"room_creation_keep_private" = "Keep private";
"room_creation_make_private" = "Make private";
"room_creation_wait_for_creation" = "A room is already being created. Please wait.";
"room_creation_invite_another_user" = "Search / invite by name, email, id";
"room_creation_invite_another_user" = "Search / invite by User ID, Name or email";

// Room recents
"room_recents_directory" = "DIRECTORY";
Expand All @@ -111,6 +111,8 @@
"search_messages" = "Messages";
"search_people" = "People";
"search_files" = "Files";
"search_default_placeholder" = "Search...";
"search_people_placeholder" = "Search by User ID, Name or email";

// Directory
"directory_cell_title" = "Browse directory";
Expand All @@ -136,7 +138,7 @@
"room_participants_invite_prompt_title" = "Invite?";
"room_participants_invite_prompt_msg" = "Are you sure you want to invite %@ to this chat?";
"room_participants_filter_room_members" = "Filter room members";
"room_participants_invite_another_user" = "Search / invite by name, email, id";
"room_participants_invite_another_user" = "Search / invite by User ID, Name or email";
"room_participants_invite_malformed_id_title" = "Invite Error";
"room_participants_invite_malformed_id" = "Malformed ID. Should be an email address or a Matrix ID like '@localpart:domain'";
"room_participants_invited_section" = "INVITED";
Expand Down
12 changes: 12 additions & 0 deletions Vector/ViewController/ContactsTableViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@
*/
@property (nonatomic) BOOL forceMatrixIdInDisplayName;

/**
The type of standard accessory view the contact cells should use
Default is UITableViewCellAccessoryNone.
*/
@property (nonatomic) UITableViewCellAccessoryType contactCellAccessoryType;

/**
An image used to create a custom accessy view on the right side of the contact cells.
If set, use custom view. ignore accessoryType
*/
@property (nonatomic) UIImage *contactCellAccessoryImage;

/**
The dictionary of the ignored local contacts, the keys are their email. Empty by default.
*/
Expand Down
17 changes: 12 additions & 5 deletions Vector/ViewController/ContactsTableViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ - (void)destroy

isMultiUseNameByDisplayName = nil;

_contactCellAccessoryImage = nil;

[super destroy];
}

Expand Down Expand Up @@ -466,6 +468,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
contactCell.accessoryView = nil;
contactCell.contentView.alpha = 1;
contactCell.userInteractionEnabled = YES;
contactCell.accessoryType = UITableViewCellAccessoryNone;
contactCell.accessoryView = nil;
}

MXKContact *contact;
Expand Down Expand Up @@ -502,24 +506,27 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
{
[contactCell render:contact];

// The search displays contacts to invite. Add a plus icon to the cell
// in order to make it more understandable for the end user
// The search displays contacts to invite.
if (indexPath.section == filteredLocalContactsSection || indexPath.section == filteredMatrixContactsSection)
{
contactCell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"plus_icon"]];
// Add the right accessory view if any
contactCell.accessoryType = self.contactCellAccessoryType;
contactCell.accessoryView = [[UIImageView alloc] initWithImage:self.contactCellAccessoryImage];
}
else if (indexPath.section == searchInputSection)
{
// This is the text entered by the user
// Check whether the search input is a valid email or a Matrix user ID before adding the plus icon.
// Check whether the search input is a valid email or a Matrix user ID before adding the accessory view.
if (![MXTools isEmailAddress:currentSearchText] && ![MXTools isMatrixUserIdentifier:currentSearchText])
{
contactCell.contentView.alpha = 0.5;
contactCell.userInteractionEnabled = NO;
}
else
{
contactCell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"plus_icon"]];
// Add the right accessory view if any
contactCell.accessoryType = self.contactCellAccessoryType;
contactCell.accessoryView = [[UIImageView alloc] initWithImage:self.contactCellAccessoryImage];
}
}
}
Expand Down
31 changes: 21 additions & 10 deletions Vector/ViewController/HomeViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ @interface HomeViewController ()
HomeFilesSearchViewController *filesSearchViewController;
MXKSearchDataSource *filesSearchDataSource;

ContactsTableViewController *contactsViewController;
ContactsTableViewController *peopleSearchViewController;
MXKContact *selectedContact;

// Display a gradient view above the screen
Expand Down Expand Up @@ -104,9 +104,10 @@ - (void)viewDidLoad

// Add search People tab
[titles addObject: NSLocalizedStringFromTable(@"search_people", @"Vector", nil)];
contactsViewController = [ContactsTableViewController contactsTableViewController];
contactsViewController.contactsTableViewControllerDelegate = self;
[viewControllers addObject:contactsViewController];
peopleSearchViewController = [ContactsTableViewController contactsTableViewController];
peopleSearchViewController.contactsTableViewControllerDelegate = self;
peopleSearchViewController.contactCellAccessoryType = UITableViewCellAccessoryDisclosureIndicator;
[viewControllers addObject:peopleSearchViewController];

// add Files tab
[titles addObject: NSLocalizedStringFromTable(@"search_files", @"Vector", nil)];
Expand All @@ -129,6 +130,7 @@ - (void)viewDidLoad
[self initializeDataSources];

self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.searchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
}

- (void)dealloc
Expand Down Expand Up @@ -511,9 +513,9 @@ - (void)checkAndShowBackgroundImage
{
self.backgroundImageView.hidden = ((messagesSearchDataSource.serverCount != 0) || !messagesSearchViewController.noResultsLabel.isHidden || (self.keyboardHeight == 0));
}
else if (self.selectedViewController == contactsViewController)
else if (self.selectedViewController == peopleSearchViewController)
{
self.backgroundImageView.hidden = (([contactsViewController.tableView numberOfRowsInSection:0] != 0) || (self.keyboardHeight == 0));
self.backgroundImageView.hidden = (([peopleSearchViewController.tableView numberOfRowsInSection:0] != 0) || (self.keyboardHeight == 0));
}
else if (self.selectedViewController == filesSearchViewController)
{
Expand Down Expand Up @@ -546,6 +548,15 @@ - (void)setSelectedIndex:(NSUInteger)selectedIndex

if (!self.searchBarHidden)
{
if (self.selectedViewController == peopleSearchViewController)
{
self.searchBar.placeholder = NSLocalizedStringFromTable(@"search_people_placeholder", @"Vector", nil);
}
else
{
self.searchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
}

[self updateSearch];
}
}
Expand Down Expand Up @@ -1108,9 +1119,9 @@ - (void)updateSearch
});
}
}
else if (self.selectedViewController == contactsViewController)
else if (self.selectedViewController == peopleSearchViewController)
{
[contactsViewController searchWithPattern:self.searchBar.text forceReset:NO];
[peopleSearchViewController searchWithPattern:self.searchBar.text forceReset:NO];
}
else if (self.selectedViewController == filesSearchViewController)
{
Expand Down Expand Up @@ -1138,7 +1149,7 @@ - (void)updateSearch
{
[messagesSearchDataSource searchMessages:nil force:NO];
}
[contactsViewController searchWithPattern:nil forceReset:NO];
[peopleSearchViewController searchWithPattern:nil forceReset:NO];
if (filesSearchDataSource.searchText.length)
{
[filesSearchDataSource searchMessages:nil force:NO];
Expand All @@ -1157,7 +1168,7 @@ - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
// As the public room search is local, it can be updated on each text change
[self updateSearch];
}
else if (self.selectedViewController == contactsViewController)
else if (self.selectedViewController == peopleSearchViewController)
{
// As the contact search is local, it can be updated on each text change
[self updateSearch];
Expand Down
6 changes: 4 additions & 2 deletions Vector/ViewController/RoomParticipantsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ - (void)addAddParticipantButton

addParticipantButtonImageView.backgroundColor = [UIColor clearColor];
addParticipantButtonImageView.contentMode = UIViewContentModeCenter;
addParticipantButtonImageView.image = [UIImage imageNamed:@"create_room"];
addParticipantButtonImageView.image = [UIImage imageNamed:@"add_participant"];

CGFloat side = 78.0f;
NSLayoutConstraint* widthConstraint = [NSLayoutConstraint constraintWithItem:addParticipantButtonImageView
Expand Down Expand Up @@ -545,12 +545,14 @@ - (void)addAddParticipantButton

- (void)onAddParticipantButtonPressed
{
// Push the contacts table screen.
// Push the contacts picker.
contactsPickerViewController = [ContactsTableViewController contactsTableViewController];

// Set delegate to handle action on member (start chat, mention)
contactsPickerViewController.contactsTableViewControllerDelegate = self;
contactsPickerViewController.forceMatrixIdInDisplayName = YES;
// Add a plus icon to the contact cell in the contacts picker, in order to make it more understandable for the end user.
contactsPickerViewController.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.
[contactsPickerViewController.ignoredContactsByMatrixId removeAllObjects];
Expand Down
2 changes: 1 addition & 1 deletion Vector/ViewController/StartChatViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
'StartChatViewController' instance is used to prepare new room creation.
*/
@interface StartChatViewController : ContactsTableViewController <UISearchBarDelegate>
@interface StartChatViewController : ContactsTableViewController <UISearchBarDelegate, ContactsTableViewControllerDelegate>

@property (weak, nonatomic) IBOutlet UIView *searchBarHeader;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBarView;
Expand Down
68 changes: 36 additions & 32 deletions Vector/ViewController/StartChatViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ - (void)finalizeInit

// Prepare room participants
participants = [NSMutableArray array];

// Assign itself as delegate
self.contactsTableViewControllerDelegate = self;

// Add a plus icon to the contact cell when a search session is in progress,
// in order to make it more understandable for the end user.
self.contactCellAccessoryImage = [UIImage imageNamed:@"plus_icon"];;
}

- (void)viewDidLoad
Expand Down Expand Up @@ -269,13 +276,13 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
{
NSInteger count = 0;

if (section == participantsSection)
if (_isAddParticipantSearchBarEditing)
{
count = participants.count + 1;
count = [super tableView:self.tableView numberOfRowsInSection:section];
}
else
else if (section == participantsSection)
{
count = [super tableView:self.tableView numberOfRowsInSection:section];
count = participants.count + 1;
}

return count;
Expand All @@ -285,7 +292,11 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
{
UITableViewCell *cell;

if (indexPath.section == participantsSection)
if (_isAddParticipantSearchBarEditing)
{
cell = [super tableView:self.tableView cellForRowAtIndexPath:indexPath];
}
else if (indexPath.section == participantsSection)
{
ContactTableViewCell* participantCell = [tableView dequeueReusableCellWithIdentifier:@"ParticipantTableViewCellId" forIndexPath:indexPath];

Expand Down Expand Up @@ -317,10 +328,6 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N

cell = participantCell;
}
else
{
cell = [super tableView:self.tableView cellForRowAtIndexPath:indexPath];
}

return cell;
}
Expand All @@ -345,7 +352,7 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSIntege
{
CGFloat height = 0.0;

if (section != participantsSection)
if (_isAddParticipantSearchBarEditing)
{
height = [super tableView:self.tableView heightForHeaderInSection:section];
}
Expand All @@ -355,32 +362,15 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSIntege

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = indexPath.row;
MXKContact *mxkContact;

if (indexPath.section == searchInputSection)
{
mxkContact = [[MXKContact alloc] initMatrixContactWithDisplayName:currentSearchText andMatrixID:nil];
}
else if (indexPath.section == filteredLocalContactsSection)
{
mxkContact = filteredLocalContacts[row];
}
else if (indexPath.section == filteredMatrixContactsSection)
if (_isAddParticipantSearchBarEditing)
{
mxkContact = filteredMatrixContacts[row];
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}

if (mxkContact)
else
{
// Update here the mutable list of participants
[participants addObject:mxkContact];

// Refresh display by leaving search session
[self searchBarCancelButtonClicked:_searchBarView];
// Do nothing
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
Expand Down Expand Up @@ -648,4 +638,18 @@ - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
[searchBar resignFirstResponder];
}

#pragma mark - ContactsTableViewControllerDelegate

- (void)contactsTableViewController:(ContactsTableViewController *)contactsTableViewController didSelectContact:(MXKContact*)contact
{
if (contact)
{
// Update here the mutable list of participants
[participants addObject:contact];
}

// Refresh display by leaving search session
[self searchBarCancelButtonClicked:_searchBarView];
}

@end

0 comments on commit c03638a

Please sign in to comment.