2014-10-29 21:58:58 +01:00
|
|
|
//
|
|
|
|
// SignalsViewController.m
|
|
|
|
// Signal
|
|
|
|
//
|
|
|
|
// Created by Dylan Bourgeois on 27/10/14.
|
|
|
|
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2016-10-10 22:02:09 +02:00
|
|
|
#import "SignalsViewController.h"
|
|
|
|
#import "AppDelegate.h"
|
2015-12-22 12:45:09 +01:00
|
|
|
#import "InCallViewController.h"
|
2016-10-10 22:02:09 +02:00
|
|
|
#import "InboxTableViewCell.h"
|
2014-10-29 21:58:58 +01:00
|
|
|
#import "MessagesViewController.h"
|
2015-12-22 12:45:09 +01:00
|
|
|
#import "NSDate+millisecondTimeStamp.h"
|
2016-08-01 00:25:07 +02:00
|
|
|
#import "OWSContactsManager.h"
|
2016-10-10 22:02:09 +02:00
|
|
|
#import "PropertyListPreferences.h"
|
|
|
|
#import "PushManager.h"
|
|
|
|
#import "RPAccountManager.h"
|
|
|
|
#import "Signal-Swift.h"
|
2015-01-14 22:30:01 +01:00
|
|
|
#import "TSAccountManager.h"
|
2014-11-21 14:38:37 +01:00
|
|
|
#import "TSDatabaseView.h"
|
2016-08-01 00:25:07 +02:00
|
|
|
#import "TSGroupThread.h"
|
2015-12-22 12:45:09 +01:00
|
|
|
#import "TSStorageManager.h"
|
2016-10-10 22:02:09 +02:00
|
|
|
#import "UIUtil.h"
|
2015-02-21 03:47:52 +01:00
|
|
|
#import "VersionMigrations.h"
|
2016-10-14 22:59:58 +02:00
|
|
|
#import <SignalServiceKit/OWSMessageSender.h>
|
|
|
|
#import <SignalServiceKit/TSMessagesManager.h>
|
|
|
|
#import <SignalServiceKit/TSOutgoingMessage.h>
|
2014-11-21 14:38:37 +01:00
|
|
|
#import <YapDatabase/YapDatabaseViewChange.h>
|
2016-10-14 22:59:58 +02:00
|
|
|
#import <YapDatabase/YapDatabaseViewConnection.h>
|
2014-11-21 14:38:37 +01:00
|
|
|
|
2015-01-06 07:06:19 +01:00
|
|
|
#define CELL_HEIGHT 72.0f
|
2014-10-29 21:58:58 +01:00
|
|
|
#define HEADER_HEIGHT 44.0f
|
|
|
|
|
2014-12-05 23:38:13 +01:00
|
|
|
@interface SignalsViewController ()
|
2015-01-29 03:57:53 +01:00
|
|
|
|
2014-12-05 23:38:13 +01:00
|
|
|
@property (nonatomic, strong) YapDatabaseConnection *editingDbConnection;
|
2014-11-21 14:38:37 +01:00
|
|
|
@property (nonatomic, strong) YapDatabaseConnection *uiDatabaseConnection;
|
|
|
|
@property (nonatomic, strong) YapDatabaseViewMappings *threadMappings;
|
2015-01-14 22:30:01 +01:00
|
|
|
@property (nonatomic) CellState viewingThreadsIn;
|
|
|
|
@property (nonatomic) long inboxCount;
|
2015-05-23 15:54:50 +02:00
|
|
|
@property (nonatomic, retain) UISegmentedControl *segmentedControl;
|
2015-12-26 17:27:27 +01:00
|
|
|
@property (nonatomic, strong) id previewingContext;
|
2016-09-21 14:37:51 +02:00
|
|
|
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
2016-10-14 22:59:58 +02:00
|
|
|
@property (nonatomic, readonly) TSMessagesManager *messagesManager;
|
|
|
|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation SignalsViewController
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
- (instancetype)init
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
_contactsManager = [Environment getCurrent].contactsManager;
|
2016-10-14 22:59:58 +02:00
|
|
|
_messagesManager = [TSMessagesManager sharedManager];
|
|
|
|
_messageSender = [[OWSMessageSender alloc] initWithNetworkManager:[Environment getCurrent].networkManager
|
|
|
|
storageManager:[TSStorageManager sharedManager]
|
|
|
|
contactsManager:_contactsManager
|
|
|
|
contactsUpdater:[Environment getCurrent].contactsUpdater];
|
2016-09-21 14:37:51 +02:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
|
|
|
{
|
|
|
|
self = [super initWithCoder:aDecoder];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
_contactsManager = [Environment getCurrent].contactsManager;
|
2016-10-14 22:59:58 +02:00
|
|
|
_messagesManager = [TSMessagesManager sharedManager];
|
|
|
|
_messageSender = [[OWSMessageSender alloc] initWithNetworkManager:[Environment getCurrent].networkManager
|
|
|
|
storageManager:[TSStorageManager sharedManager]
|
|
|
|
contactsManager:_contactsManager
|
|
|
|
contactsUpdater:[Environment getCurrent].contactsUpdater];
|
2016-09-21 14:37:51 +02:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)awakeFromNib
|
|
|
|
{
|
|
|
|
[super awakeFromNib];
|
2014-11-26 20:29:45 +01:00
|
|
|
[[Environment getCurrent] setSignalsViewController:self];
|
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
- (void)viewDidLoad {
|
|
|
|
[super viewDidLoad];
|
2015-01-14 22:30:01 +01:00
|
|
|
[self.navigationController.navigationBar setTranslucent:NO];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-12-05 23:38:13 +01:00
|
|
|
[self tableViewSetUp];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-12-05 23:38:13 +01:00
|
|
|
self.editingDbConnection = TSStorageManager.sharedManager.newDatabaseConnection;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.uiDatabaseConnection beginLongLivedReadTransaction];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(yapDatabaseModified:)
|
|
|
|
name:TSUIDatabaseConnectionDidUpdateNotification
|
|
|
|
object:nil];
|
2015-01-14 22:30:01 +01:00
|
|
|
[self selectedInbox:self];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
[[[Environment getCurrent] contactsManager]
|
|
|
|
.getObservableContacts watchLatestValue:^(id latestValue) {
|
|
|
|
[self.tableView reloadData];
|
|
|
|
}
|
|
|
|
onThread:[NSThread mainThread]
|
|
|
|
untilCancelled:nil];
|
|
|
|
|
|
|
|
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[
|
|
|
|
NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil),
|
|
|
|
NSLocalizedString(@"ARCHIVE_NAV_BAR_TITLE", nil)
|
|
|
|
]];
|
|
|
|
|
|
|
|
[self.segmentedControl addTarget:self
|
|
|
|
action:@selector(swappedSegmentedControl)
|
|
|
|
forControlEvents:UIControlEventValueChanged];
|
2015-05-23 15:54:50 +02:00
|
|
|
self.navigationItem.titleView = self.segmentedControl;
|
|
|
|
[self.segmentedControl setSelectedSegmentIndex:0];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] &&
|
|
|
|
(self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) {
|
2015-12-26 17:27:27 +01:00
|
|
|
[self registerForPreviewingWithDelegate:self sourceView:self.tableView];
|
2015-10-31 16:53:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext
|
2015-10-31 16:53:32 +01:00
|
|
|
viewControllerForLocation:(CGPoint)location {
|
2015-12-22 12:45:09 +01:00
|
|
|
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
|
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
if (indexPath) {
|
|
|
|
[previewingContext setSourceRect:[self.tableView rectForRowAtIndexPath:indexPath]];
|
|
|
|
|
|
|
|
MessagesViewController *vc = [[MessagesViewController alloc] initWithNibName:nil bundle:nil];
|
|
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
|
|
[vc configureForThread:thread keyboardOnViewAppearing:NO];
|
|
|
|
[vc peekSetup];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
return vc;
|
|
|
|
} else {
|
|
|
|
return nil;
|
|
|
|
}
|
2015-10-31 16:53:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext
|
|
|
|
commitViewController:(UIViewController *)viewControllerToCommit {
|
2015-12-22 12:45:09 +01:00
|
|
|
MessagesViewController *vc = (MessagesViewController *)viewControllerToCommit;
|
2015-10-31 16:53:32 +01:00
|
|
|
[vc popped];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
[self.navigationController pushViewController:vc animated:NO];
|
2015-10-31 16:53:32 +01:00
|
|
|
}
|
|
|
|
|
2015-10-31 23:13:28 +01:00
|
|
|
- (void)composeNew {
|
|
|
|
if (self.presentedViewController) {
|
|
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-10-31 23:13:28 +01:00
|
|
|
[self.navigationController popToRootViewControllerAnimated:YES];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-10-31 23:13:28 +01:00
|
|
|
[self performSegueWithIdentifier:@"composeNew" sender:self];
|
|
|
|
}
|
|
|
|
|
2015-05-23 15:54:50 +02:00
|
|
|
- (void)swappedSegmentedControl {
|
|
|
|
if (self.segmentedControl.selectedSegmentIndex == 0) {
|
|
|
|
[self selectedInbox:nil];
|
|
|
|
} else {
|
|
|
|
[self selectedArchive:nil];
|
|
|
|
}
|
2014-11-24 21:51:43 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)viewWillAppear:(BOOL)animated {
|
2014-11-24 21:51:43 +01:00
|
|
|
[super viewWillAppear:animated];
|
2015-12-22 12:45:09 +01:00
|
|
|
[self checkIfEmptyView];
|
|
|
|
|
2016-04-01 17:34:47 +02:00
|
|
|
[self updateInboxCountLabel];
|
|
|
|
[[self tableView] reloadData];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidAppear:(BOOL)animated {
|
|
|
|
[super viewDidAppear:animated];
|
2016-10-10 22:02:09 +02:00
|
|
|
if (self.newlyRegisteredUser) {
|
|
|
|
[self didAppearForNewlyRegisteredUser];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)didAppearForNewlyRegisteredUser
|
|
|
|
{
|
|
|
|
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
|
|
|
|
switch (status) {
|
|
|
|
case kABAuthorizationStatusNotDetermined:
|
|
|
|
case kABAuthorizationStatusRestricted: {
|
|
|
|
UIAlertController *controller =
|
|
|
|
[UIAlertController alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil)
|
|
|
|
message:NSLocalizedString(@"REGISTER_CONTACTS_BODY", nil)
|
|
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
|
|
|
|
[controller
|
|
|
|
addAction:[UIAlertAction
|
|
|
|
actionWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_CONTINUE", nil)
|
|
|
|
style:UIAlertActionStyleCancel
|
|
|
|
handler:^(UIAlertAction *action) {
|
2016-11-12 21:32:45 +01:00
|
|
|
[self ensureNotificationsUpToDate];
|
2016-10-10 22:02:09 +02:00
|
|
|
[[Environment getCurrent].contactsManager doAfterEnvironmentInitSetup];
|
|
|
|
}]];
|
|
|
|
|
2016-11-12 21:32:45 +01:00
|
|
|
[self presentViewController:controller animated:YES completion:nil];
|
2016-10-10 22:02:09 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
DDLogError(@"%@ Unexpected for new user to have kABAuthorizationStatus:%ld", self.tag, status);
|
2016-11-12 21:32:45 +01:00
|
|
|
[self ensureNotificationsUpToDate];
|
2016-10-10 22:02:09 +02:00
|
|
|
[[Environment getCurrent].contactsManager doAfterEnvironmentInitSetup];
|
2016-11-12 21:32:45 +01:00
|
|
|
|
2016-10-10 22:02:09 +02:00
|
|
|
break;
|
|
|
|
}
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
2015-02-17 00:14:50 +01:00
|
|
|
}
|
|
|
|
|
2016-10-10 22:02:09 +02:00
|
|
|
- (void)ensureNotificationsUpToDate
|
|
|
|
{
|
|
|
|
OWSAccountManager *accountManager =
|
|
|
|
[[OWSAccountManager alloc] initWithTextSecureAccountManager:[TSAccountManager sharedInstance]
|
|
|
|
redPhoneAccountManager:[RPAccountManager sharedInstance]];
|
|
|
|
|
|
|
|
OWSSyncPushTokensJob *syncPushTokensJob =
|
|
|
|
[[OWSSyncPushTokensJob alloc] initWithPushManager:[PushManager sharedManager]
|
|
|
|
accountManager:accountManager
|
|
|
|
preferences:[Environment preferences]];
|
|
|
|
[syncPushTokensJob run];
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)tableViewSetUp {
|
2014-11-21 14:38:37 +01:00
|
|
|
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-01-24 04:26:04 +01:00
|
|
|
#pragma mark - Table View Data Source
|
2014-10-29 21:58:58 +01:00
|
|
|
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
2014-11-21 14:38:37 +01:00
|
|
|
return (NSInteger)[self.threadMappings numberOfSections];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
2014-11-21 14:38:37 +01:00
|
|
|
return (NSInteger)[self.threadMappings numberOfItemsInSection:(NSUInteger)section];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (InboxTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
InboxTableViewCell *cell =
|
|
|
|
[self.tableView dequeueReusableCellWithIdentifier:NSStringFromClass([InboxTableViewCell class])];
|
|
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
if (!cell) {
|
2015-12-26 17:27:27 +01:00
|
|
|
cell = [InboxTableViewCell inboxTableViewCell];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-10-31 16:53:32 +01:00
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
2016-09-21 14:37:51 +02:00
|
|
|
[cell configureWithThread:thread contactsManager:self.contactsManager];
|
2015-10-31 16:53:32 +01:00
|
|
|
});
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
if ((unsigned long)indexPath.row == [self.threadMappings numberOfItemsInSection:0] - 1) {
|
2015-03-20 14:32:57 +01:00
|
|
|
cell.separatorInset = UIEdgeInsetsMake(0.f, cell.bounds.size.width, 0.f, 0.f);
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
return cell;
|
2014-11-21 14:38:37 +01:00
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (TSThread *)threadForIndexPath:(NSIndexPath *)indexPath {
|
2014-11-21 14:38:37 +01:00
|
|
|
__block TSThread *thread = nil;
|
|
|
|
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
2015-12-22 12:45:09 +01:00
|
|
|
thread = [[transaction extension:TSThreadDatabaseViewExtensionName] objectAtIndexPath:indexPath
|
|
|
|
withMappings:self.threadMappings];
|
2014-11-21 14:38:37 +01:00
|
|
|
}];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
return thread;
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
return CELL_HEIGHT;
|
|
|
|
}
|
2014-10-29 21:58:58 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
#pragma mark Table Swipe to Delete
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)tableView:(UITableView *)tableView
|
|
|
|
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
|
|
|
|
forRowAtIndexPath:(NSIndexPath *)indexPath {
|
2015-01-14 22:30:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-01-27 21:17:49 +01:00
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
UITableViewRowAction *deleteAction =
|
|
|
|
[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault
|
2015-12-26 17:27:27 +01:00
|
|
|
title:NSLocalizedString(@"TXT_DELETE_TITLE", nil)
|
2015-12-22 12:45:09 +01:00
|
|
|
handler:^(UITableViewRowAction *action, NSIndexPath *swipedIndexPath) {
|
|
|
|
[self tableViewCellTappedDelete:swipedIndexPath];
|
|
|
|
}];
|
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
UITableViewRowAction *archiveAction;
|
|
|
|
if (self.viewingThreadsIn == kInboxState) {
|
|
|
|
archiveAction = [UITableViewRowAction
|
|
|
|
rowActionWithStyle:UITableViewRowActionStyleNormal
|
2016-05-09 02:17:37 +02:00
|
|
|
title:NSLocalizedString(@"ARCHIVE_ACTION", @"Pressing this button moves a thread from the inbox to the archive")
|
2015-12-26 17:27:27 +01:00
|
|
|
handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull tappedIndexPath) {
|
|
|
|
[self archiveIndexPath:tappedIndexPath];
|
|
|
|
[Environment.preferences setHasArchivedAMessage:YES];
|
|
|
|
}];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
} else {
|
|
|
|
archiveAction = [UITableViewRowAction
|
|
|
|
rowActionWithStyle:UITableViewRowActionStyleNormal
|
2016-05-09 02:17:37 +02:00
|
|
|
title:NSLocalizedString(@"UNARCHIVE_ACTION", @"Pressing this button moves an archived thread from the archive back to the inbox")
|
2015-12-26 17:27:27 +01:00
|
|
|
handler:^(UITableViewRowAction *_Nonnull action, NSIndexPath *_Nonnull tappedIndexPath) {
|
|
|
|
[self archiveIndexPath:tappedIndexPath];
|
|
|
|
}];
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
return @[ deleteAction, archiveAction ];
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
#pragma mark - HomeFeedTableViewCellDelegate
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)tableViewCellTappedDelete:(NSIndexPath *)indexPath {
|
|
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
|
|
if ([thread isKindOfClass:[TSGroupThread class]]) {
|
2015-12-26 17:27:27 +01:00
|
|
|
UIAlertController *removingFromGroup = [UIAlertController
|
|
|
|
alertControllerWithTitle:[NSString
|
|
|
|
stringWithFormat:NSLocalizedString(@"GROUP_REMOVING", nil), [thread name]]
|
|
|
|
message:nil
|
|
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
[self presentViewController:removingFromGroup animated:YES completion:nil];
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
|
|
|
inThread:thread
|
|
|
|
messageBody:@""
|
2016-08-01 00:25:07 +02:00
|
|
|
attachmentIds:[NSMutableArray new]];
|
2014-12-24 02:25:10 +01:00
|
|
|
message.groupMetaMessage = TSGroupMessageQuit;
|
2016-10-14 22:59:58 +02:00
|
|
|
[self.messageSender sendMessage:message
|
2015-12-26 17:27:27 +01:00
|
|
|
success:^{
|
2016-10-14 22:59:58 +02:00
|
|
|
[self dismissViewControllerAnimated:YES
|
|
|
|
completion:^{
|
|
|
|
[self deleteThread:thread];
|
|
|
|
}];
|
2015-12-26 17:27:27 +01:00
|
|
|
}
|
2016-10-14 22:59:58 +02:00
|
|
|
failure:^(NSError *error) {
|
|
|
|
[self dismissViewControllerAnimated:YES
|
|
|
|
completion:^{
|
|
|
|
SignalAlertView(NSLocalizedString(@"GROUP_REMOVING_FAILED", nil),
|
|
|
|
error.localizedRecoverySuggestion);
|
|
|
|
}];
|
2015-12-26 17:27:27 +01:00
|
|
|
}];
|
|
|
|
} else {
|
|
|
|
[self deleteThread:thread];
|
2014-12-24 02:25:10 +01:00
|
|
|
}
|
2015-12-26 17:27:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)deleteThread:(TSThread *)thread {
|
2014-12-05 23:38:13 +01:00
|
|
|
[self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
2015-12-22 12:45:09 +01:00
|
|
|
[thread removeWithTransaction:transaction];
|
2014-12-05 23:38:13 +01:00
|
|
|
}];
|
2015-12-26 17:27:27 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
_inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0;
|
2015-01-27 02:20:11 +01:00
|
|
|
[self checkIfEmptyView];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-26 17:27:27 +01:00
|
|
|
- (void)archiveIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-07-10 15:00:14 +02:00
|
|
|
BOOL viewingThreadsIn = self.viewingThreadsIn;
|
2014-12-05 23:38:13 +01:00
|
|
|
[self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
2015-12-22 12:45:09 +01:00
|
|
|
viewingThreadsIn == kInboxState ? [thread archiveThreadWithTransaction:transaction]
|
|
|
|
: [thread unarchiveThreadWithTransaction:transaction];
|
|
|
|
|
2014-12-05 23:38:13 +01:00
|
|
|
}];
|
2015-01-27 02:20:11 +01:00
|
|
|
[self checkIfEmptyView];
|
2015-01-14 22:30:01 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (NSNumber *)updateInboxCountLabel {
|
2016-10-14 22:59:58 +02:00
|
|
|
NSUInteger numberOfItems = [self.messagesManager unreadMessagesCount];
|
2015-05-23 15:54:50 +02:00
|
|
|
NSNumber *badgeNumber = [NSNumber numberWithUnsignedInteger:numberOfItems];
|
|
|
|
NSString *unreadString = NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil);
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-02-10 12:02:58 +01:00
|
|
|
if (![badgeNumber isEqualToNumber:@0]) {
|
2015-12-22 12:45:09 +01:00
|
|
|
NSString *badgeValue = [badgeNumber stringValue];
|
|
|
|
unreadString = [unreadString stringByAppendingFormat:@" (%@)", badgeValue];
|
2015-02-10 12:02:58 +01:00
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-05-23 15:54:50 +02:00
|
|
|
[_segmentedControl setTitle:unreadString forSegmentAtIndex:0];
|
2015-09-01 19:22:08 +02:00
|
|
|
[_segmentedControl reloadInputViews];
|
2015-04-14 21:49:00 +02:00
|
|
|
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeNumber.integerValue];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2015-05-23 15:54:50 +02:00
|
|
|
return badgeNumber;
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
2015-12-26 17:27:27 +01:00
|
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
|
|
[self presentThread:thread keyboardOnViewAppearing:NO];
|
|
|
|
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)presentThread:(TSThread *)thread keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing {
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
2016-10-10 22:02:09 +02:00
|
|
|
MessagesViewController *mvc = [[UIStoryboard storyboardWithName:AppDelegateStoryboardMain bundle:NULL]
|
|
|
|
instantiateViewControllerWithIdentifier:@"MessagesViewController"];
|
2015-12-26 17:27:27 +01:00
|
|
|
|
2016-10-10 22:02:09 +02:00
|
|
|
if (self.presentedViewController) {
|
|
|
|
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
|
|
|
[self.navigationController popToRootViewControllerAnimated:YES];
|
2015-12-26 17:27:27 +01:00
|
|
|
|
2016-10-10 22:02:09 +02:00
|
|
|
[mvc configureForThread:thread keyboardOnViewAppearing:keyboardOnViewAppearing];
|
|
|
|
[self.navigationController pushViewController:mvc animated:YES];
|
2015-12-26 17:27:27 +01:00
|
|
|
});
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Navigation
|
|
|
|
|
|
|
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
2015-12-26 17:27:27 +01:00
|
|
|
if ([segue.identifier isEqualToString:kCallSegue]) {
|
2015-12-22 12:45:09 +01:00
|
|
|
InCallViewController *vc = [segue destinationViewController];
|
2015-01-14 22:30:01 +01:00
|
|
|
[vc configureWithLatestCall:_latestCall];
|
|
|
|
_latestCall = nil;
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - IBAction
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (IBAction)selectedInbox:(id)sender {
|
2015-01-14 22:30:01 +01:00
|
|
|
self.viewingThreadsIn = kInboxState;
|
|
|
|
[self changeToGrouping:TSInboxGroup];
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (IBAction)selectedArchive:(id)sender {
|
2015-01-14 22:30:01 +01:00
|
|
|
self.viewingThreadsIn = kArchiveState;
|
|
|
|
[self changeToGrouping:TSArchiveGroup];
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)changeToGrouping:(NSString *)grouping {
|
|
|
|
self.threadMappings =
|
|
|
|
[[YapDatabaseViewMappings alloc] initWithGroups:@[ grouping ] view:TSThreadDatabaseViewExtensionName];
|
2015-02-16 10:27:08 +01:00
|
|
|
[self.threadMappings setIsReversed:YES forGroup:grouping];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
[self.uiDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
|
|
[self.threadMappings updateWithTransaction:transaction];
|
|
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self.tableView reloadData];
|
|
|
|
[self checkIfEmptyView];
|
|
|
|
});
|
2014-12-05 23:38:13 +01:00
|
|
|
}];
|
2014-10-29 21:58:58 +01:00
|
|
|
}
|
2014-11-21 14:38:37 +01:00
|
|
|
|
|
|
|
#pragma mark Database delegates
|
|
|
|
|
|
|
|
- (YapDatabaseConnection *)uiDatabaseConnection {
|
|
|
|
NSAssert([NSThread isMainThread], @"Must access uiDatabaseConnection on main thread!");
|
|
|
|
if (!_uiDatabaseConnection) {
|
|
|
|
YapDatabase *database = TSStorageManager.sharedManager.database;
|
|
|
|
_uiDatabaseConnection = [database newConnection];
|
|
|
|
[_uiDatabaseConnection beginLongLivedReadTransaction];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(yapDatabaseModified:)
|
|
|
|
name:YapDatabaseModifiedNotification
|
|
|
|
object:database];
|
|
|
|
}
|
|
|
|
return _uiDatabaseConnection;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)yapDatabaseModified:(NSNotification *)notification {
|
2014-11-25 17:28:42 +01:00
|
|
|
NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction];
|
2014-11-21 14:38:37 +01:00
|
|
|
NSArray *sectionChanges = nil;
|
2014-11-25 17:28:42 +01:00
|
|
|
NSArray *rowChanges = nil;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
[[self.uiDatabaseConnection ext:TSThreadDatabaseViewExtensionName] getSectionChanges:§ionChanges
|
|
|
|
rowChanges:&rowChanges
|
|
|
|
forNotifications:notifications
|
|
|
|
withMappings:self.threadMappings];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2016-09-01 17:14:58 +02:00
|
|
|
// We want this regardless of if we're currently viewing the archive.
|
|
|
|
// So we run it before the early return
|
|
|
|
[self updateInboxCountLabel];
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
if ([sectionChanges count] == 0 && [rowChanges count] == 0) {
|
2014-11-21 14:38:37 +01:00
|
|
|
return;
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView beginUpdates];
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
for (YapDatabaseViewSectionChange *sectionChange in sectionChanges) {
|
|
|
|
switch (sectionChange.type) {
|
|
|
|
case YapDatabaseViewChangeDelete: {
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionChange.index]
|
|
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
|
|
break;
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
case YapDatabaseViewChangeInsert: {
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionChange.index]
|
|
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case YapDatabaseViewChangeUpdate:
|
|
|
|
case YapDatabaseViewChangeMove:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
for (YapDatabaseViewRowChange *rowChange in rowChanges) {
|
|
|
|
switch (rowChange.type) {
|
|
|
|
case YapDatabaseViewChangeDelete: {
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ]
|
|
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
2015-01-14 22:30:01 +01:00
|
|
|
_inboxCount += (self.viewingThreadsIn == kArchiveState) ? 1 : 0;
|
2014-11-21 14:38:37 +01:00
|
|
|
break;
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
case YapDatabaseViewChangeInsert: {
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ]
|
|
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
2015-01-14 22:30:01 +01:00
|
|
|
_inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0;
|
2014-11-21 14:38:37 +01:00
|
|
|
break;
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
case YapDatabaseViewChangeMove: {
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ]
|
|
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
|
|
[self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ]
|
|
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
|
|
break;
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
case YapDatabaseViewChangeUpdate: {
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView reloadRowsAtIndexPaths:@[ rowChange.indexPath ]
|
|
|
|
withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
|
2014-11-21 14:38:37 +01:00
|
|
|
[self.tableView endUpdates];
|
2015-01-27 02:20:11 +01:00
|
|
|
[self checkIfEmptyView];
|
2014-11-21 14:38:37 +01:00
|
|
|
}
|
2014-11-25 19:06:09 +01:00
|
|
|
|
2015-01-14 22:30:01 +01:00
|
|
|
|
|
|
|
- (IBAction)unwindSettingsDone:(UIStoryboardSegue *)segue {
|
|
|
|
}
|
|
|
|
|
|
|
|
- (IBAction)unwindMessagesView:(UIStoryboardSegue *)segue {
|
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)checkIfEmptyView {
|
2015-01-27 02:20:11 +01:00
|
|
|
[_tableView setHidden:NO];
|
2015-12-22 12:45:09 +01:00
|
|
|
if (self.viewingThreadsIn == kInboxState && [self.threadMappings numberOfItemsInGroup:TSInboxGroup] == 0) {
|
2015-01-27 21:17:49 +01:00
|
|
|
[self setEmptyBoxText];
|
2015-01-27 02:20:11 +01:00
|
|
|
[_tableView setHidden:YES];
|
2015-12-22 12:45:09 +01:00
|
|
|
} else if (self.viewingThreadsIn == kArchiveState &&
|
|
|
|
[self.threadMappings numberOfItemsInGroup:TSArchiveGroup] == 0) {
|
2015-01-27 21:17:49 +01:00
|
|
|
[self setEmptyBoxText];
|
2015-01-27 02:20:11 +01:00
|
|
|
[_tableView setHidden:YES];
|
2014-11-25 19:06:09 +01:00
|
|
|
}
|
2015-01-27 21:17:49 +01:00
|
|
|
}
|
|
|
|
|
2015-12-22 12:45:09 +01:00
|
|
|
- (void)setEmptyBoxText {
|
|
|
|
_emptyBoxLabel.textColor = [UIColor grayColor];
|
|
|
|
_emptyBoxLabel.font = [UIFont ows_regularFontWithSize:18.f];
|
2015-01-27 21:17:49 +01:00
|
|
|
_emptyBoxLabel.textAlignment = NSTextAlignmentCenter;
|
|
|
|
_emptyBoxLabel.numberOfLines = 4;
|
2015-12-22 12:45:09 +01:00
|
|
|
|
|
|
|
NSString *firstLine = @"";
|
|
|
|
NSString *secondLine = @"";
|
|
|
|
|
|
|
|
if (self.viewingThreadsIn == kInboxState) {
|
|
|
|
if ([Environment.preferences getHasSentAMessage]) {
|
|
|
|
firstLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TITLE", @"");
|
2015-02-18 23:21:03 +01:00
|
|
|
secondLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TEXT", @"");
|
2015-12-22 12:45:09 +01:00
|
|
|
} else {
|
2016-08-10 15:58:34 +02:00
|
|
|
// FIXME This looks wrong. Shouldn't we be showing inbox_title/text here?
|
2015-12-22 12:45:09 +01:00
|
|
|
firstLine = NSLocalizedString(@"EMPTY_ARCHIVE_FIRST_TITLE", @"");
|
2015-02-18 23:21:03 +01:00
|
|
|
secondLine = NSLocalizedString(@"EMPTY_ARCHIVE_FIRST_TEXT", @"");
|
2015-02-09 17:31:22 +01:00
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
} else {
|
|
|
|
if ([Environment.preferences getHasArchivedAMessage]) {
|
2016-08-10 15:58:34 +02:00
|
|
|
// FIXME This looks wrong. Shouldn't we be showing first_archive_title/text here?
|
2015-12-22 12:45:09 +01:00
|
|
|
firstLine = NSLocalizedString(@"EMPTY_INBOX_TITLE", @"");
|
|
|
|
secondLine = NSLocalizedString(@"EMPTY_INBOX_TEXT", @"");
|
|
|
|
} else {
|
|
|
|
firstLine = NSLocalizedString(@"EMPTY_ARCHIVE_TITLE", @"");
|
|
|
|
secondLine = NSLocalizedString(@"EMPTY_ARCHIVE_TEXT", @"");
|
2015-02-09 17:31:22 +01:00
|
|
|
}
|
2015-01-27 21:17:49 +01:00
|
|
|
}
|
2015-12-22 12:45:09 +01:00
|
|
|
NSMutableAttributedString *fullLabelString =
|
|
|
|
[[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@", firstLine, secondLine]];
|
|
|
|
|
|
|
|
[fullLabelString addAttribute:NSFontAttributeName
|
|
|
|
value:[UIFont ows_boldFontWithSize:15.f]
|
|
|
|
range:NSMakeRange(0, firstLine.length)];
|
|
|
|
[fullLabelString addAttribute:NSFontAttributeName
|
|
|
|
value:[UIFont ows_regularFontWithSize:14.f]
|
|
|
|
range:NSMakeRange(firstLine.length + 1, secondLine.length)];
|
|
|
|
[fullLabelString addAttribute:NSForegroundColorAttributeName
|
|
|
|
value:[UIColor blackColor]
|
|
|
|
range:NSMakeRange(0, firstLine.length)];
|
|
|
|
[fullLabelString addAttribute:NSForegroundColorAttributeName
|
|
|
|
value:[UIColor ows_darkGrayColor]
|
|
|
|
range:NSMakeRange(firstLine.length + 1, secondLine.length)];
|
2015-01-27 21:17:49 +01:00
|
|
|
_emptyBoxLabel.attributedText = fullLabelString;
|
2014-11-25 19:06:09 +01:00
|
|
|
}
|
|
|
|
|
2016-10-10 22:02:09 +02:00
|
|
|
#pragma mark - Logging
|
|
|
|
|
|
|
|
+ (NSString *)tag
|
|
|
|
{
|
|
|
|
return [NSString stringWithFormat:@"[%@]", self.class];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)tag
|
|
|
|
{
|
|
|
|
return self.class.tag;
|
|
|
|
}
|
|
|
|
|
2014-10-29 21:58:58 +01:00
|
|
|
@end
|