diff --git a/Monal/Classes/ContactsViewController.h b/Monal/Classes/ContactsViewController.h deleted file mode 100644 index 86190c6ad..000000000 --- a/Monal/Classes/ContactsViewController.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// ContactsViewController.h -// Monal -// -// Created by Anurodh Pokharel on 6/14/13. -// -// - -#import -#import "MLConstants.h" -#import "MLImageManager.h" -#import "MLContact.h" -#import - -@interface ContactsViewController : UITableViewController - -@property (nonatomic, weak) UITableView* contactsTable; -@property (nonatomic, strong) contactCompletion selectContact; - --(IBAction) close:(id) sender; - -@end diff --git a/Monal/Classes/ContactsViewController.m b/Monal/Classes/ContactsViewController.m deleted file mode 100644 index 2a3372caa..000000000 --- a/Monal/Classes/ContactsViewController.m +++ /dev/null @@ -1,465 +0,0 @@ -// -// ContactsViewController.m -// Monal -// -// Created by Anurodh Pokharel on 6/14/13. -// -// - -#import "ContactsViewController.h" -#import "MLContactCell.h" -#import "DataLayer.h" -#import "chatViewController.h" -#import "MonalAppDelegate.h" -#import "xmpp.h" -#import -#import "HelperTools.h" - -@interface DZNEmptyDataSetView -@property (atomic, strong) UIView* contentView; -@property (atomic, strong) UIImageView* imageView; -@property (atomic, strong) UILabel* titleLabel; -@property (atomic, strong) UILabel* detailLabel; -@end - -@interface UIScrollView () -@property (nonatomic, readonly) DZNEmptyDataSetView* emptyDataSetView; -@end - -@interface ContactsViewController () -@property (nonatomic, strong) UISearchController* searchController; -@property (nonatomic, strong) NSMutableArray* contacts; -@property (nonatomic, strong) MLContact* lastSelectedContact; -@end - -@implementation ContactsViewController - --(void) openAddContacts:(id)sender -{ - UIViewController* addContactMenuView = [[SwiftuiInterface new] makeAddContactViewWithDismisser:^(MLContact* _Nonnull newContact) { - dispatch_async(dispatch_get_main_queue(), ^{ - DDLogVerbose(@"Calling block self.selectContact: %@", self.selectContact); - if(self.selectContact) - self.selectContact(newContact); - }); - }]; - [self presentViewController:addContactMenuView animated:YES completion:^{}]; -} - --(void) openCreateGroup:(id) sender -{ - UIViewController* createGroupView = [[SwiftuiInterface new] makeViewWithName:@"CreateGroup"]; - [self presentViewController:createGroupView animated:YES completion:^{}]; -} - --(void) configureAddContactImage -{ - UIImage* image = [[UIImage systemImageNamed:@"person.fill.badge.plus"] imageWithTintColor:UIColor.tintColor]; - UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openAddContacts:)]; - self.navigationItem.rightBarButtonItems[0].customView = [HelperTools - buttonWithNotificationBadgeForImage:image - hasNotification:[[DataLayer sharedInstance] allContactRequests].count > 0 - withTapHandler:tapRecognizer]; - [self.navigationItem.rightBarButtonItems[0] setIsAccessibilityElement:YES]; - if([[DataLayer sharedInstance] allContactRequests].count > 0) - [self.navigationItem.rightBarButtonItems[0] setAccessibilityLabel:NSLocalizedString(@"Add contact (contact requests pending)", @"")]; - else - [self.navigationItem.rightBarButtonItems[0] setAccessibilityLabel:NSLocalizedString(@"Add contact", @"")]; - [self.navigationItem.rightBarButtonItems[0] setAccessibilityTraits:UIAccessibilityTraitButton]; -} - -#pragma mark view life cycle - --(void) viewDidLoad -{ - [super viewDidLoad]; - // Do any additional setup after loading the view from its nib. - self.navigationItem.title=NSLocalizedString(@"Contacts", @""); - - self.contactsTable = self.tableView; - self.contactsTable.delegate = self; - self.contactsTable.dataSource = self; - - self.contacts = [NSMutableArray new]; - - [self.contactsTable reloadData]; - - [self.contactsTable registerNib:[UINib nibWithNibName:@"MLContactCell" - bundle:[NSBundle mainBundle]] - forCellReuseIdentifier:@"ContactCell"]; - - self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeOneBesideSecondary; - - self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; - - self.searchController.searchResultsUpdater = self; - self.searchController.delegate = self; - self.searchController.obscuresBackgroundDuringPresentation = NO; - self.definesPresentationContext = YES; - - self.tableView.emptyDataSetSource = self; - self.tableView.emptyDataSetDelegate = self; - - UIBarButtonItem* createGroup = [[UIBarButtonItem alloc] init]; - createGroup.image = [UIImage systemImageNamed:@"person.3.fill"]; - createGroup.accessibilityLabel = @"Create contact group"; - [createGroup setAction:@selector(openCreateGroup:)]; - [createGroup setTarget:self]; - - self.navigationItem.rightBarButtonItems = @[[[UIBarButtonItem alloc] init], createGroup]; - - [self configureAddContactImage]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleContactUpdate) name:kMonalContactRemoved object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleContactUpdate) name:kMonalContactRefresh object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeviceRotation) name:UIDeviceOrientationDidChangeNotification object:nil]; -} - --(void) handleContactUpdate -{ - dispatch_async(dispatch_get_main_queue(), ^{ - [self reloadTable]; - }); -} - --(void) handleDeviceRotation -{ - dispatch_async(dispatch_get_main_queue(), ^{ - [self imageForEmptyDataSet:nil]; - }); -} - --(void) dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - --(void) viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - self.lastSelectedContact = nil; - [self refreshDisplay]; - - if(self.contacts.count < 1) - { - self.navigationItem.searchController = nil; - [self reloadTable]; - } - else - self.navigationItem.searchController = self.searchController; -} - - --(void) viewDidAppear:(BOOL) animated -{ - [super viewDidAppear:animated]; -} - - --(void) viewWillDisappear:(BOOL) animated -{ - [super viewWillDisappear:animated]; -} - --(void) didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - --(BOOL) canBecomeFirstResponder -{ - return YES; -} - --(NSArray*) keyCommands { - return @[ - [UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:0 action:@selector(close:)] - ]; -} - -#pragma mark - message signals - --(void) reloadTable -{ - [self configureAddContactImage]; - if(self.contactsTable.hasUncommittedUpdates) - return; - [self.contactsTable reloadData]; -} - --(void) refreshDisplay -{ - [self loadContactsWithFilter:nil]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self reloadTable]; - }); -} - - -#pragma mark - chat presentation - --(BOOL) shouldPerformSegueWithIdentifier:(NSString*) identifier sender:(id) sender -{ - return YES; -} - -//this is needed to prevent segues invoked programmatically --(void) performSegueWithIdentifier:(NSString*) identifier sender:(id) sender -{ - if([self shouldPerformSegueWithIdentifier:identifier sender:sender] == NO) - return; - if([identifier isEqualToString:@"showDetails"]) - { - UIViewController* detailsViewController = [[SwiftuiInterface new] makeContactDetails:sender]; - [self presentViewController:detailsViewController animated:YES completion:^{}]; - return; - } - [super performSegueWithIdentifier:identifier sender:sender]; -} - --(void) loadContactsWithFilter:(NSString*) filter -{ - NSArray* contacts; - if(filter && [filter length] > 0) - self.contacts = [[DataLayer sharedInstance] searchContactsWithString:filter]; - else - { - contacts = [[DataLayer sharedInstance] contactList]; - BOOL onlySelfChats = YES; - NSMutableArray* contactsToDisplay = [NSMutableArray new]; - for(MLContact* contact in contacts) - { - if(!contact.isSelfChat) - onlySelfChats = NO; -#ifdef IS_QUICKSY - [contactsToDisplay addObject:contact]; -#else - //ignore all contacts not at least in any roster state: e.g. subscribedTo or asking state - //OR is subscribedFrom (e.g. we approved them already, bit they don't approve us) - if((contact.isSubscribedTo || contact.hasOutgoingContactRequest) || contact.isSubscribedFrom) - [contactsToDisplay addObject:contact]; -#endif - } - if(!onlySelfChats) - self.contacts = contactsToDisplay; - else - self.contacts = [NSMutableArray new]; - } -} - -#pragma mark - Search Controller - --(void) didDismissSearchController:(UISearchController*) searchController -{ - // reset table to list of all contacts without a filter - [self loadContactsWithFilter:nil]; - [self reloadTable]; -} - --(void) updateSearchResultsForSearchController:(UISearchController*) searchController -{ - [self loadContactsWithFilter:searchController.searchBar.text]; - [self reloadTable]; -} - -#pragma mark - tableview datasource - --(NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section -{ - return nil; -} - --(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView -{ - return 1; -} - -- (NSInteger)tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger) section -{ - return [self.contacts count]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - MLContact* contact = [self.contacts objectAtIndex:indexPath.row]; - - MLContactCell* cell = [tableView dequeueReusableCellWithIdentifier:@"ContactCell"]; - if(!cell) - cell = [[MLContactCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"ContactCell"]; - [cell initCell:contact withLastMessage:nil]; - cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; - - return cell; -} - -#pragma mark - tableview delegate - --(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - return 60.0f; -} - --(NSString*) tableView:(UITableView*) tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath*) indexPath -{ - MLAssert(indexPath.section == 0, @"Wrong section"); - MLContact* contact = self.contacts[indexPath.row]; - if(contact.isMuc == YES) - return NSLocalizedString(@"Remove Conversation", @""); - else - return NSLocalizedString(@"Remove Contact", @""); -} - --(BOOL) tableView:(UITableView*) tableView canEditRowAtIndexPath:(NSIndexPath*) indexPath -{ - if(tableView == self.view) - { - //don't allow deletion for self-chats - MLContact* contact = [self.contacts objectAtIndex:indexPath.row]; - return !contact.isSelfChat; - } - else - return NO; -} - --(BOOL) tableView:(UITableView*) tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath*) indexPath -{ - if(tableView == self.view) - return YES; - else - return NO; -} - --(void) deleteRowAtIndexPath:(NSIndexPath *) indexPath -{ - MLContact* contact = [self.contacts objectAtIndex:indexPath.row]; - NSString* messageString = [NSString stringWithFormat:NSLocalizedString(@"Remove %@ from contacts?", @""), contact.contactJid]; - NSString* detailString = NSLocalizedString(@"They will no longer see when you are online. They may not be able to access your encryption keys.", @""); - - if(contact.isMuc) - { - messageString = NSLocalizedString(@"Leave this converstion?", @""); - detailString = nil; - } - - UIAlertController* alert = [UIAlertController alertControllerWithTitle:messageString - message:detailString preferredStyle:UIAlertControllerStyleActionSheet]; - [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"No", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action __unused) { - [alert dismissViewControllerAnimated:YES completion:nil]; - }]]; - - [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Yes", @"") style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action __unused) { - // remove contact - [[MLXMPPManager sharedInstance] removeContact:contact]; - // remove contact from table - [self.contactsTable beginUpdates]; - [self.contacts removeObjectAtIndex:indexPath.row]; - [self.contactsTable deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; - [self.contactsTable endUpdates]; - }]]; - alert.popoverPresentationController.sourceView = self.tableView; - [self presentViewController:alert animated:YES completion:nil]; -} - --(void) tableView:(UITableView*) tableView commitEditingStyle:(UITableViewCellEditingStyle) editingStyle forRowAtIndexPath:(NSIndexPath*) indexPath -{ - if(editingStyle == UITableViewCellEditingStyleDelete) - [self deleteRowAtIndexPath:indexPath]; -} - --(void) tableView:(UITableView*) tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath*) indexPath -{ - MLContact* contactDic = [self.contacts objectAtIndex:indexPath.row]; - [self performSegueWithIdentifier:@"showDetails" sender:contactDic]; -} - --(void) tableView:(UITableView*) tableView didSelectRowAtIndexPath:(NSIndexPath*) indexPath -{ - MLContact* row = [self.contacts objectAtIndex:indexPath.row]; - - [self dismissViewControllerAnimated:YES completion:^{ - if(self.selectContact) - self.selectContact(row); - }]; - -} - -#pragma mark - empty data set - --(UIImage*) imageForEmptyDataSet:(UIScrollView*) scrollView -{ - DZNEmptyDataSetView* emptyDataSetView = self.tableView.emptyDataSetView; - CGRect headerFrame = self.navigationController.navigationBar.frame; - CGRect tableFrame = self.tableView.frame; - //CGRect contentFrame = emptyDataSetView.contentView.frame; - //DDLogError(@"headerFrame: %@", NSStringFromCGRect(headerFrame)); - //DDLogError(@"tableFrame: %@", NSStringFromCGRect(tableFrame)); - //DDLogError(@"contentFrame: %@", NSStringFromCGRect(contentFrame)); - //emptyDataSetView.contentView.frame = tableFrame; - tableFrame.size.height *= 0.5; - tableFrame.origin.y -= headerFrame.size.height; - emptyDataSetView.imageView.frame = tableFrame; - [emptyDataSetView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView]-(64@750)-[titleLabel]-(16@750)-[detailLabel]|" options:0 metrics:nil views:@{ - @"imageView": emptyDataSetView.imageView, - @"titleLabel": emptyDataSetView.titleLabel, - @"detailLabel": emptyDataSetView.detailLabel, - }]]; - emptyDataSetView.imageView.translatesAutoresizingMaskIntoConstraints = YES; - if(self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) - return [UIImage imageNamed:@"friends_dark"]; - return [UIImage imageNamed:@"friends"]; -} - --(CGFloat) spaceHeightForEmptyDataSet:(UIScrollView*) scrollView -{ - return 48.0f; -} - --(NSAttributedString*) titleForEmptyDataSet:(UIScrollView*) scrollView -{ - NSString* text = NSLocalizedString(@"You need friends for this ride", @""); - - NSDictionary* attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:18.0f], - NSForegroundColorAttributeName: (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor whiteColor] : [UIColor blackColor])}; - - return [[NSAttributedString alloc] initWithString:text attributes:attributes]; -} - --(NSAttributedString*) descriptionForEmptyDataSet:(UIScrollView*) scrollView -{ - NSString *text = NSLocalizedString(@"Add new contacts with the + button above. Your friends will pop up here when they can talk", @""); - - NSMutableParagraphStyle *paragraph = [NSMutableParagraphStyle new]; - paragraph.lineBreakMode = NSLineBreakByWordWrapping; - paragraph.alignment = NSTextAlignmentCenter; - - NSDictionary* attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:14.0f], - NSForegroundColorAttributeName: (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor whiteColor] : [UIColor blackColor]), - NSParagraphStyleAttributeName: paragraph}; - - return [[NSAttributedString alloc] initWithString:text attributes:attributes]; -} - --(UIColor*) backgroundColorForEmptyDataSet:(UIScrollView*) scrollView -{ - return [UIColor colorNamed:@"contacts"]; -} - --(BOOL) emptyDataSetShouldDisplay:(UIScrollView*) scrollView -{ - if(self.contacts.count < 1) - { - // A little trick for removing the cell separators - self.tableView.tableFooterView = [UIView new]; - } - return self.contacts.count < 1; -} - --(IBAction) close:(id) sender -{ - [self dismissViewControllerAnimated:YES completion:nil]; -} - -@end diff --git a/Monal/Monal.xcodeproj/project.pbxproj b/Monal/Monal.xcodeproj/project.pbxproj index 48d62d6de..9dc28fb2a 100644 --- a/Monal/Monal.xcodeproj/project.pbxproj +++ b/Monal/Monal.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 2609B5291FD5B26800F09FA1 /* MLSplitViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2609B5281FD5B26800F09FA1 /* MLSplitViewDelegate.m */; }; 26158AF21FFA6E4500E53BDC /* MLWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 26158AF11FFA6E4500E53BDC /* MLWebViewController.m */; }; 26158AF41FFA8A6A00E53BDC /* opensource.html in Resources */ = {isa = PBXBuildFile; fileRef = 26158AF31FFA8A6A00E53BDC /* opensource.html */; }; - 261A6281176C055400059090 /* ContactsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 261A627F176C055400059090 /* ContactsViewController.m */; }; 261A628B176C159000059090 /* AccountListController.m in Sources */ = {isa = PBXBuildFile; fileRef = 261A628A176C159000059090 /* AccountListController.m */; }; 261E542523A0A1D300394F59 /* monalxmpp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26CC579223A0867400ABB92A /* monalxmpp.framework */; }; 261E542623A0A1D300394F59 /* monalxmpp.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 26CC579223A0867400ABB92A /* monalxmpp.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -339,8 +338,6 @@ 26158AF01FFA6E4500E53BDC /* MLWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MLWebViewController.h; sourceTree = ""; }; 26158AF11FFA6E4500E53BDC /* MLWebViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MLWebViewController.m; sourceTree = ""; }; 26158AF31FFA8A6A00E53BDC /* opensource.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = opensource.html; sourceTree = ""; }; - 261A627E176C055400059090 /* ContactsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsViewController.h; sourceTree = ""; }; - 261A627F176C055400059090 /* ContactsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsViewController.m; sourceTree = ""; }; 261A6284176C156500059090 /* ActiveChatsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActiveChatsViewController.m; sourceTree = ""; }; 261A6289176C159000059090 /* AccountListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccountListController.h; sourceTree = ""; }; 261A628A176C159000059090 /* AccountListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AccountListController.m; sourceTree = ""; }; @@ -1224,8 +1221,6 @@ 268C1E471FDACDD300BD6921 /* Contact Details */, 2665C1191C4AA22700CC9A04 /* Accounts */, 262797AC178A573F00B85D94 /* Tableviewcells */, - 261A627E176C055400059090 /* ContactsViewController.h */, - 261A627F176C055400059090 /* ContactsViewController.m */, 261A6284176C156500059090 /* ActiveChatsViewController.m */, 2609B5271FD5B26800F09FA1 /* MLSplitViewDelegate.h */, 2609B5281FD5B26800F09FA1 /* MLSplitViewDelegate.m */, @@ -2090,7 +2085,6 @@ E89DD32525C6626400925F62 /* MLFileTransferDataCell.m in Sources */, E89DD32825C6626400925F62 /* MLFileTransferTextCell.m in Sources */, 84BBAECA2C42D272009492E2 /* Quicksy_RegisterAccount.swift in Sources */, - 261A6281176C055400059090 /* ContactsViewController.m in Sources */, 26B0CA8921AE2E3C0080B133 /* MLSoundsTableViewController.m in Sources */, 84D31CE628653B83006D7926 /* WebRTCClient.swift in Sources */, 54F0B81C282316F5003664BD /* RegisterAccount.swift in Sources */,