mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Usinig the new ShareViewDelegate to dismiss the share extension, might have broken the "import with signal" functionality. But because we want to remove it anyway, I've done that now, rather than fix it up. // FREEBIE
307 lines
11 KiB
Objective-C
307 lines
11 KiB
Objective-C
//
|
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
#import "SelectThreadViewController.h"
|
|
#import "BlockListUIUtils.h"
|
|
#import "ContactTableViewCell.h"
|
|
#import "ContactsViewHelper.h"
|
|
#import "Environment.h"
|
|
#import "NSString+OWS.h"
|
|
#import "OWSContactsManager.h"
|
|
#import "OWSTableViewController.h"
|
|
#import "ThreadViewHelper.h"
|
|
#import "UIColor+OWS.h"
|
|
#import "UIFont+OWS.h"
|
|
#import "UIView+OWS.h"
|
|
#import <SignalMessaging/SignalMessaging-Swift.h>
|
|
#import <SignalServiceKit/PhoneNumber.h>
|
|
#import <SignalServiceKit/SignalAccount.h>
|
|
#import <SignalServiceKit/TSAccountManager.h>
|
|
#import <SignalServiceKit/TSContactThread.h>
|
|
#import <SignalServiceKit/TSThread.h>
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
@interface SelectThreadViewController () <OWSTableViewControllerDelegate,
|
|
ThreadViewHelperDelegate,
|
|
ContactsViewHelperDelegate,
|
|
UISearchBarDelegate>
|
|
|
|
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
|
|
@property (nonatomic, readonly) ConversationSearcher *conversationSearcher;
|
|
@property (nonatomic, readonly) ThreadViewHelper *threadViewHelper;
|
|
|
|
@property (nonatomic, readonly) OWSTableViewController *tableViewController;
|
|
|
|
@property (nonatomic, readonly) UISearchBar *searchBar;
|
|
|
|
@end
|
|
|
|
#pragma mark -
|
|
|
|
@implementation SelectThreadViewController
|
|
|
|
- (void)loadView
|
|
{
|
|
[super loadView];
|
|
|
|
self.navigationItem.leftBarButtonItem =
|
|
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
|
|
target:self
|
|
action:@selector(dismissPressed:)];
|
|
|
|
self.view.backgroundColor = [UIColor whiteColor];
|
|
|
|
_contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self];
|
|
_conversationSearcher = ConversationSearcher.shared;
|
|
_threadViewHelper = [ThreadViewHelper new];
|
|
_threadViewHelper.delegate = self;
|
|
|
|
[self createViews];
|
|
|
|
[self updateTableContents];
|
|
}
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
[self.navigationController.navigationBar setTranslucent:NO];
|
|
}
|
|
|
|
- (void)createViews
|
|
{
|
|
OWSAssert(self.selectThreadViewDelegate);
|
|
|
|
// Search
|
|
UISearchBar *searchBar = [UISearchBar new];
|
|
_searchBar = searchBar;
|
|
searchBar.searchBarStyle = UISearchBarStyleMinimal;
|
|
searchBar.delegate = self;
|
|
searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @"");
|
|
searchBar.backgroundColor = [UIColor whiteColor];
|
|
[searchBar sizeToFit];
|
|
|
|
UIView *header = [self.selectThreadViewDelegate createHeaderWithSearchBar:searchBar];
|
|
|
|
// Table
|
|
_tableViewController = [OWSTableViewController new];
|
|
_tableViewController.delegate = self;
|
|
[self.view addSubview:self.tableViewController.view];
|
|
[_tableViewController.view autoPinWidthToSuperview];
|
|
[_tableViewController.view autoPinToTopLayoutGuideOfViewController:self withInset:0];
|
|
if (header) {
|
|
_tableViewController.tableView.tableHeaderView = header;
|
|
} else {
|
|
_tableViewController.tableView.tableHeaderView = searchBar;
|
|
}
|
|
[self autoPinViewToBottomGuideOrKeyboard:self.tableViewController.view];
|
|
}
|
|
|
|
#pragma mark - UISearchBarDelegate
|
|
|
|
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
- (void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
#pragma mark - Table Contents
|
|
|
|
- (void)updateTableContents
|
|
{
|
|
__weak SelectThreadViewController *weakSelf = self;
|
|
ContactsViewHelper *helper = self.contactsViewHelper;
|
|
OWSTableContents *contents = [OWSTableContents new];
|
|
|
|
// Existing threads are listed first, ordered by most recently active
|
|
OWSTableSection *recentChatsSection = [OWSTableSection new];
|
|
recentChatsSection.headerTitle = NSLocalizedString(
|
|
@"SELECT_THREAD_TABLE_RECENT_CHATS_TITLE", @"Table section header for recently active conversations");
|
|
for (TSThread *thread in [self filteredThreadsWithSearchText]) {
|
|
[recentChatsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
|
SelectThreadViewController *strongSelf = weakSelf;
|
|
OWSCAssert(strongSelf);
|
|
|
|
// To be consistent with the threads (above), we use ContactTableViewCell
|
|
// instead of InboxTableViewCell to present contacts and threads.
|
|
ContactTableViewCell *cell = [ContactTableViewCell new];
|
|
[cell configureWithThread:thread contactsManager:helper.contactsManager];
|
|
return cell;
|
|
}
|
|
customRowHeight:[ContactTableViewCell rowHeight]
|
|
actionBlock:^{
|
|
[weakSelf.selectThreadViewDelegate threadWasSelected:thread];
|
|
}]];
|
|
}
|
|
|
|
if (recentChatsSection.itemCount > 0) {
|
|
[contents addSection:recentChatsSection];
|
|
}
|
|
|
|
// Contacts who don't yet have a thread are listed last
|
|
OWSTableSection *otherContactsSection = [OWSTableSection new];
|
|
otherContactsSection.headerTitle = NSLocalizedString(
|
|
@"SELECT_THREAD_TABLE_OTHER_CHATS_TITLE", @"Table section header for conversations you haven't recently used.");
|
|
NSArray<SignalAccount *> *filteredSignalAccounts = [self filteredSignalAccountsWithSearchText];
|
|
for (SignalAccount *signalAccount in filteredSignalAccounts) {
|
|
[otherContactsSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
|
SelectThreadViewController *strongSelf = weakSelf;
|
|
OWSCAssert(strongSelf);
|
|
|
|
ContactTableViewCell *cell = [ContactTableViewCell new];
|
|
BOOL isBlocked = [helper isRecipientIdBlocked:signalAccount.recipientId];
|
|
if (isBlocked) {
|
|
cell.accessoryMessage
|
|
= NSLocalizedString(@"CONTACT_CELL_IS_BLOCKED", @"An indicator that a contact has been blocked.");
|
|
} else {
|
|
OWSAssert(cell.accessoryMessage == nil);
|
|
}
|
|
[cell configureWithSignalAccount:signalAccount contactsManager:helper.contactsManager];
|
|
return cell;
|
|
}
|
|
customRowHeight:[ContactTableViewCell rowHeight]
|
|
actionBlock:^{
|
|
[weakSelf signalAccountWasSelected:signalAccount];
|
|
}]];
|
|
}
|
|
|
|
if (otherContactsSection.itemCount > 0) {
|
|
[contents addSection:otherContactsSection];
|
|
}
|
|
|
|
if (recentChatsSection.itemCount + otherContactsSection.itemCount < 1) {
|
|
OWSTableSection *emptySection = [OWSTableSection new];
|
|
[emptySection
|
|
addItem:[OWSTableItem
|
|
softCenterLabelItemWithText:NSLocalizedString(@"SETTINGS_BLOCK_LIST_NO_CONTACTS",
|
|
@"A label that indicates the user has no Signal contacts.")]];
|
|
[contents addSection:emptySection];
|
|
}
|
|
|
|
self.tableViewController.contents = contents;
|
|
}
|
|
|
|
- (void)signalAccountWasSelected:(SignalAccount *)signalAccount
|
|
{
|
|
OWSAssert(signalAccount);
|
|
OWSAssert(self.selectThreadViewDelegate);
|
|
|
|
ContactsViewHelper *helper = self.contactsViewHelper;
|
|
|
|
if ([helper isRecipientIdBlocked:signalAccount.recipientId]
|
|
&& ![self.selectThreadViewDelegate canSelectBlockedContact]) {
|
|
|
|
__weak SelectThreadViewController *weakSelf = self;
|
|
[BlockListUIUtils showUnblockSignalAccountActionSheet:signalAccount
|
|
fromViewController:self
|
|
blockingManager:helper.blockingManager
|
|
contactsManager:helper.contactsManager
|
|
completionBlock:^(BOOL isBlocked) {
|
|
if (!isBlocked) {
|
|
[weakSelf signalAccountWasSelected:signalAccount];
|
|
}
|
|
}];
|
|
return;
|
|
}
|
|
|
|
__block TSThread *thread = nil;
|
|
[[TSStorageManager sharedManager].dbReadWriteConnection
|
|
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
thread = [TSContactThread getOrCreateThreadWithContactId:signalAccount.recipientId transaction:transaction];
|
|
}];
|
|
OWSAssert(thread);
|
|
|
|
[self.selectThreadViewDelegate threadWasSelected:thread];
|
|
}
|
|
|
|
#pragma mark - Filter
|
|
|
|
- (NSArray<TSThread *> *)filteredThreadsWithSearchText
|
|
{
|
|
NSString *searchTerm = [[self.searchBar text] ows_stripped];
|
|
|
|
return [self.conversationSearcher filterThreads:self.threadViewHelper.threads withSearchText:searchTerm];
|
|
}
|
|
|
|
- (NSArray<SignalAccount *> *)filteredSignalAccountsWithSearchText
|
|
{
|
|
// We don't want to show a 1:1 thread with Alice and Alice's contact,
|
|
// so we de-duplicate by recipientId.
|
|
NSArray<TSThread *> *threads = self.threadViewHelper.threads;
|
|
NSMutableSet *contactIdsToIgnore = [NSMutableSet new];
|
|
for (TSThread *thread in threads) {
|
|
if ([thread isKindOfClass:[TSContactThread class]]) {
|
|
TSContactThread *contactThread = (TSContactThread *)thread;
|
|
[contactIdsToIgnore addObject:contactThread.contactIdentifier];
|
|
}
|
|
}
|
|
|
|
NSString *searchString = self.searchBar.text;
|
|
NSArray<SignalAccount *> *matchingAccounts =
|
|
[self.contactsViewHelper signalAccountsMatchingSearchString:searchString];
|
|
|
|
return [matchingAccounts
|
|
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SignalAccount *signalAccount,
|
|
NSDictionary<NSString *, id> *_Nullable bindings) {
|
|
return ![contactIdsToIgnore containsObject:signalAccount.recipientId];
|
|
}]];
|
|
}
|
|
|
|
#pragma mark - Events
|
|
|
|
- (void)dismissPressed:(id)sender
|
|
{
|
|
[self.searchBar resignFirstResponder];
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
}
|
|
|
|
#pragma mark - OWSTableViewControllerDelegate
|
|
|
|
- (void)tableViewWillBeginDragging
|
|
{
|
|
[self.searchBar resignFirstResponder];
|
|
}
|
|
|
|
#pragma mark - ThreadViewHelperDelegate
|
|
|
|
- (void)threadListDidChange
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
#pragma mark - ContactsViewHelperDelegate
|
|
|
|
- (void)contactsViewHelperDidUpdateContacts
|
|
{
|
|
[self updateTableContents];
|
|
}
|
|
|
|
- (BOOL)shouldHideLocalNumber
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|