Add possibility to add multiple participants at once.

Signed-off-by: Ivan Sein <ivan@nextcloud.com>
This commit is contained in:
Ivan Sein 2018-06-18 17:38:25 +02:00
Родитель 7e6d21dbbb
Коммит e78701d44e
4 изменённых файлов: 215 добавлений и 33 удалений

Просмотреть файл

@ -95,6 +95,7 @@
2CBF82BE1FD5AE0A00636459 /* NCImageSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CBF82BC1FD5AE0A00636459 /* NCImageSessionManager.m */; };
2CBF82C11FD5AE3F00636459 /* NCPushProxySessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CBF82C01FD5AE3F00636459 /* NCPushProxySessionManager.m */; };
2CBF82C21FD5AE3F00636459 /* NCPushProxySessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CBF82C01FD5AE3F00636459 /* NCPushProxySessionManager.m */; };
2CC007B420D7AE990096D91F /* ResultMultiSelectionTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC007B320D7AE990096D91F /* ResultMultiSelectionTableViewController.m */; };
2CC7158920B837140045C789 /* ChatPlaceholderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CC7158820B837140045C789 /* ChatPlaceholderView.xib */; };
2CC7158C20B8394A0045C789 /* ChatPlaceholderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CC7158B20B8394A0045C789 /* ChatPlaceholderView.m */; };
2CC7158E20C51ABA0045C789 /* UnreadMessagesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2CC7158D20C51ABA0045C789 /* UnreadMessagesView.xib */; };
@ -331,6 +332,8 @@
2CBF82BC1FD5AE0A00636459 /* NCImageSessionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCImageSessionManager.m; sourceTree = "<group>"; };
2CBF82BF1FD5AE3F00636459 /* NCPushProxySessionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCPushProxySessionManager.h; sourceTree = "<group>"; };
2CBF82C01FD5AE3F00636459 /* NCPushProxySessionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCPushProxySessionManager.m; sourceTree = "<group>"; };
2CC007B220D7AE990096D91F /* ResultMultiSelectionTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ResultMultiSelectionTableViewController.h; sourceTree = "<group>"; };
2CC007B320D7AE990096D91F /* ResultMultiSelectionTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ResultMultiSelectionTableViewController.m; sourceTree = "<group>"; };
2CC7158820B837140045C789 /* ChatPlaceholderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ChatPlaceholderView.xib; sourceTree = "<group>"; };
2CC7158A20B8394A0045C789 /* ChatPlaceholderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChatPlaceholderView.h; sourceTree = "<group>"; };
2CC7158B20B8394A0045C789 /* ChatPlaceholderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChatPlaceholderView.m; sourceTree = "<group>"; };
@ -523,6 +526,8 @@
2C7A123F2017872600864818 /* AddParticipantsTableViewController.h */,
2C7A12402017872600864818 /* AddParticipantsTableViewController.m */,
2C7A12412017872600864818 /* AddParticipantsTableViewController.xib */,
2CC007B220D7AE990096D91F /* ResultMultiSelectionTableViewController.h */,
2CC007B320D7AE990096D91F /* ResultMultiSelectionTableViewController.m */,
);
name = Contacts;
sourceTree = "<group>";
@ -1024,6 +1029,7 @@
2C0574851EDD9E8E00D9E7F2 /* AppDelegate.m in Sources */,
2C78EFA91F87EF39008AFA74 /* NBMPeersFlowLayout.m in Sources */,
2CA1CCDB1F1F6FCA002FE6A2 /* RoomTableViewCell.m in Sources */,
2CC007B420D7AE990096D91F /* ResultMultiSelectionTableViewController.m in Sources */,
2CA1CCC31F166CC5002FE6A2 /* NCRoom.m in Sources */,
2C06BF5D20A89F510031EB46 /* NCRoomsManager.m in Sources */,
2CA1CCA71F026222002FE6A2 /* ContactsTableViewController.m in Sources */,

Просмотреть файл

@ -9,18 +9,20 @@
#import "AddParticipantsTableViewController.h"
#import "NCAPIController.h"
#import "SearchTableViewController.h"
#import "NCUserInterfaceController.h"
#import "ResultMultiSelectionTableViewController.h"
#import "UIImageView+Letters.h"
#import "UIImageView+AFNetworking.h"
@interface AddParticipantsTableViewController () <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
{
NCRoom *_room;
NSMutableDictionary *_participants;
NSArray *_indexes;
NSArray *_alreadyAddedParticipants;
NCRoom *_room;
NSArray *_participantsInRoom;
UISearchController *_searchController;
SearchTableViewController *_resultTableViewController;
ResultMultiSelectionTableViewController *_resultTableViewController;
NSMutableArray *_selectedParticipants;
}
@end
@ -34,9 +36,10 @@
}
_room = room;
_participantsInRoom = [room.participants allKeys];
_participants = [[NSMutableDictionary alloc] init];
_indexes = [[NSArray alloc] init];
_alreadyAddedParticipants = [room.participants allKeys];
_selectedParticipants = [[NSMutableArray alloc] init];
return self;
}
@ -49,7 +52,7 @@
self.tableView.separatorInset = UIEdgeInsetsMake(0, 72, 0, 0);
self.tableView.sectionIndexBackgroundColor = [UIColor clearColor];
_resultTableViewController = [[SearchTableViewController alloc] init];
_resultTableViewController = [[ResultMultiSelectionTableViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:_resultTableViewController];
_searchController.searchResultsUpdater = self;
[_searchController.searchBar sizeToFit];
@ -71,6 +74,8 @@
_resultTableViewController.tableView.delegate = self;
_searchController.delegate = self;
_searchController.searchBar.delegate = self;
_searchController.hidesNavigationBarDuringPresentation = NO;
self.definesPresentationContext = YES;
@ -130,13 +135,57 @@
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
- (void)addButtonPressed
{
self.tableView.allowsSelection = NO;
_resultTableViewController.tableView.allowsSelection = NO;
for (NCUser *participant in _selectedParticipants) {
[self addParticipantToRoom:participant];
}
[self close];
}
- (void)addParticipantToRoom:(NCUser *)participant
{
[[NCAPIController sharedInstance] addParticipant:participant.userId toRoom:_room.token withCompletionBlock:^(NSError *error) {
if (error) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Could not add participant"
message:[NSString stringWithFormat:@"An error occurred while adding %@ to the room", participant.name]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil];
[alert addAction:okButton];
[[NCUserInterfaceController sharedInstance] presentAlertViewController:alert];
}
}];
}
- (void)updateCounter
{
if (_selectedParticipants.count > 0) {
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithTitle:[NSString stringWithFormat:@"Add (%lu)", (unsigned long)_selectedParticipants.count]
style:UIBarButtonItemStylePlain target:self action:@selector(addButtonPressed)];
self.navigationController.navigationBar.topItem.rightBarButtonItem = addButton;
} else {
self.navigationController.navigationBar.topItem.rightBarButtonItem = nil;
}
}
#pragma mark - Participants actions
- (NSMutableArray *)filterContacts:(NSMutableArray *)contacts
{
NSMutableArray *participants = [[NSMutableArray alloc] init];
for (NCUser *user in contacts) {
if (![_alreadyAddedParticipants containsObject:user.userId]) {
if (![_participantsInRoom containsObject:user.userId]) {
[participants addObject:user];
}
}
@ -173,6 +222,30 @@
}];
}
- (BOOL)isParticipantAlreadySelected:(NCUser *)participant
{
for (NCUser *user in _selectedParticipants) {
if ([user.userId isEqualToString:participant.userId]) {
return YES;
}
}
return NO;
}
- (void)removeSelectedParticipant:(NCUser *)participant
{
NCUser *userToDelete = nil;
for (NCUser *user in _selectedParticipants) {
if ([user.userId isEqualToString:participant.userId]) {
userToDelete = user;
}
}
if (userToDelete) {
[_selectedParticipants removeObject:userToDelete];
}
}
#pragma mark - Search controller
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
@ -180,6 +253,11 @@
[self searchForParticipantsWithString:_searchController.searchBar.text];
}
- (void)didDismissSearchController:(UISearchController *)searchController
{
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@ -207,7 +285,8 @@
return _indexes;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *index = [_indexes objectAtIndex:indexPath.section];
NSArray *participants = [_participants objectForKey:index];
NCUser *participant = [participants objectAtIndex:indexPath.row];
@ -229,6 +308,7 @@
cell.contactImage.layer.cornerRadius = 24.0;
cell.contactImage.layer.masksToBounds = YES;
cell.accessoryType = ([self isParticipantAlreadySelected:participant]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
@ -247,33 +327,19 @@
}
NCUser *participant = [participants objectAtIndex:indexPath.row];
if (![self isParticipantAlreadySelected:participant]) {
[_selectedParticipants addObject:participant];
} else {
[self removeSelectedParticipant:participant];
}
self.tableView.allowsSelection = NO;
_resultTableViewController.tableView.allowsSelection = NO;
_resultTableViewController.selectedParticipants = _selectedParticipants;
[[NCAPIController sharedInstance] addParticipant:participant.userId toRoom:_room.token withCompletionBlock:^(NSError *error) {
if (!error) {
[self close];
} else {
self.tableView.allowsSelection = YES;
_resultTableViewController.tableView.allowsSelection = YES;
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Could not add participant"
message:[NSString stringWithFormat:@"An error occurred while adding %@ to the room", participant.name]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil];
[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
}
}];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
[self updateCounter];
}
@end

Просмотреть файл

@ -0,0 +1,19 @@
//
// ResultMultiSelectionTableViewController.h
// VideoCalls
//
// Created by Ivan Sein on 18.06.18.
// Copyright © 2018 struktur AG. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ContactsTableViewCell.h"
@interface ResultMultiSelectionTableViewController : UITableViewController
@property (nonatomic, strong) NSMutableDictionary *contacts;
@property (nonatomic, strong) NSArray *indexes;
@property (nonatomic, strong) NSMutableArray *selectedParticipants;
@end

Просмотреть файл

@ -0,0 +1,91 @@
//
// ResultMultiSelectionTableViewController.m
// VideoCalls
//
// Created by Ivan Sein on 18.06.18.
// Copyright © 2018 struktur AG. All rights reserved.
//
#import "ResultMultiSelectionTableViewController.h"
#import "NCUser.h"
#import "NCAPIController.h"
#import "UIImageView+Letters.h"
#import "UIImageView+AFNetworking.h"
@interface ResultMultiSelectionTableViewController ()
@end
@implementation ResultMultiSelectionTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:kContactsTableCellNibName bundle:nil] forCellReuseIdentifier:kContactCellIdentifier];
// Align header's title to ContactsTableViewCell's label
self.tableView.separatorInset = UIEdgeInsetsMake(0, 72, 0, 0);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return _indexes.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *index = [_indexes objectAtIndex:section];
NSArray *contacts = [_contacts objectForKey:index];
return contacts.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0f;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [_indexes objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *index = [_indexes objectAtIndex:indexPath.section];
NSArray *contacts = [_contacts objectForKey:index];
NCUser *contact = [contacts objectAtIndex:indexPath.row];
ContactsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kContactCellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[ContactsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kContactCellIdentifier];
}
cell.labelTitle.text = contact.name;
// Create avatar for every contact
[cell.contactImage setImageWithString:contact.name color:nil circular:true];
// Request user avatar to the server and set it if exist
[cell.contactImage setImageWithURLRequest:[[NCAPIController sharedInstance] createAvatarRequestForUser:contact.userId andSize:96]
placeholderImage:nil
success:nil
failure:nil];
cell.contactImage.layer.cornerRadius = 24.0;
cell.contactImage.layer.masksToBounds = YES;
cell.accessoryType = UITableViewCellAccessoryNone;
for (NCUser *user in _selectedParticipants) {
if ([user.userId isEqualToString:contact.userId]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
return cell;
}
@end