2017-02-17 23:30:49 +01:00
|
|
|
//
|
|
|
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
|
|
|
//
|
2016-09-21 14:37:51 +02:00
|
|
|
|
|
|
|
#import "OWSConversationSettingsTableViewController.h"
|
2017-04-03 16:29:11 +02:00
|
|
|
#import "BlockListUIUtils.h"
|
2017-05-09 23:55:18 +02:00
|
|
|
#import "ContactsViewHelper.h"
|
2016-09-21 14:37:51 +02:00
|
|
|
#import "Environment.h"
|
|
|
|
#import "FingerprintViewController.h"
|
|
|
|
#import "OWSAvatarBuilder.h"
|
2017-04-03 16:29:11 +02:00
|
|
|
#import "OWSBlockingManager.h"
|
2016-09-21 14:37:51 +02:00
|
|
|
#import "OWSContactsManager.h"
|
|
|
|
#import "PhoneNumber.h"
|
|
|
|
#import "ShowGroupMembersViewController.h"
|
2017-04-21 23:03:18 +02:00
|
|
|
#import "Signal-Swift.h"
|
2016-10-06 15:44:25 +02:00
|
|
|
#import "UIFont+OWS.h"
|
2016-10-14 22:59:58 +02:00
|
|
|
#import "UIUtil.h"
|
2017-04-17 21:13:15 +02:00
|
|
|
#import "UIView+OWS.h"
|
2017-04-28 18:18:42 +02:00
|
|
|
#import "UpdateGroupViewController.h"
|
2016-09-21 14:37:51 +02:00
|
|
|
#import <25519/Curve25519.h>
|
|
|
|
#import <SignalServiceKit/NSDate+millisecondTimeStamp.h>
|
|
|
|
#import <SignalServiceKit/OWSDisappearingConfigurationUpdateInfoMessage.h>
|
|
|
|
#import <SignalServiceKit/OWSDisappearingMessagesConfiguration.h>
|
|
|
|
#import <SignalServiceKit/OWSFingerprint.h>
|
|
|
|
#import <SignalServiceKit/OWSFingerprintBuilder.h>
|
2016-10-14 22:59:58 +02:00
|
|
|
#import <SignalServiceKit/OWSMessageSender.h>
|
2016-09-21 14:37:51 +02:00
|
|
|
#import <SignalServiceKit/OWSNotifyRemoteOfUpdatedDisappearingConfigurationJob.h>
|
|
|
|
#import <SignalServiceKit/TSGroupThread.h>
|
2016-10-14 22:59:58 +02:00
|
|
|
#import <SignalServiceKit/TSOutgoingMessage.h>
|
2016-09-21 14:37:51 +02:00
|
|
|
#import <SignalServiceKit/TSStorageManager.h>
|
|
|
|
#import <SignalServiceKit/TSThread.h>
|
|
|
|
|
2017-05-09 23:55:18 +02:00
|
|
|
@import ContactsUI;
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
|
2017-05-09 23:55:18 +02:00
|
|
|
@interface OWSConversationSettingsTableViewController () <ContactEditingDelegate, ContactsViewHelperDelegate>
|
2016-09-21 14:37:51 +02:00
|
|
|
|
|
|
|
@property (nonatomic) TSThread *thread;
|
|
|
|
|
|
|
|
@property (nonatomic) NSArray<NSNumber *> *disappearingMessagesDurations;
|
|
|
|
@property (nonatomic) OWSDisappearingMessagesConfiguration *disappearingMessagesConfiguration;
|
|
|
|
|
|
|
|
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
|
|
|
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
2016-10-14 22:59:58 +02:00
|
|
|
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
2017-04-03 16:29:11 +02:00
|
|
|
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
2017-05-09 23:55:18 +02:00
|
|
|
@property (nonatomic, readonly) ContactsViewHelper *contactsViewHelper;
|
2017-04-21 21:37:51 +02:00
|
|
|
@property (nonatomic, readonly) UIImageView *avatarView;
|
2017-04-17 21:13:15 +02:00
|
|
|
@property (nonatomic, readonly) UILabel *disappearingMessagesDurationLabel;
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
@end
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
#pragma mark -
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
@implementation OWSConversationSettingsTableViewController
|
|
|
|
|
|
|
|
- (instancetype)init
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2017-03-10 14:59:59 +01:00
|
|
|
[self commonInit];
|
2016-09-21 14:37:51 +02:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
|
|
|
|
{
|
|
|
|
self = [super initWithCoder:aDecoder];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2017-03-10 14:59:59 +01:00
|
|
|
[self commonInit];
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil {
|
|
|
|
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
|
|
|
if (!self) {
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
[self commonInit];
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)commonInit
|
|
|
|
{
|
2016-09-21 14:37:51 +02:00
|
|
|
_storageManager = [TSStorageManager sharedManager];
|
2016-10-14 22:59:58 +02:00
|
|
|
_contactsManager = [Environment getCurrent].contactsManager;
|
2017-03-30 18:51:48 +02:00
|
|
|
_messageSender = [Environment getCurrent].messageSender;
|
2017-04-03 16:29:11 +02:00
|
|
|
_blockingManager = [OWSBlockingManager sharedManager];
|
2017-05-12 17:09:25 +02:00
|
|
|
_contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
- (NSString *)threadName
|
|
|
|
{
|
|
|
|
NSString *threadName = self.thread.name;
|
|
|
|
if ([threadName isEqualToString:self.thread.contactIdentifier]) {
|
|
|
|
threadName =
|
|
|
|
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:self.thread.contactIdentifier];
|
|
|
|
} else if (threadName.length == 0 && [self isGroupThread]) {
|
|
|
|
threadName = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @"");
|
|
|
|
}
|
|
|
|
return threadName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isGroupThread
|
|
|
|
{
|
|
|
|
return [self.thread isKindOfClass:[TSGroupThread class]];
|
|
|
|
}
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
- (void)configureWithThread:(TSThread *)thread
|
|
|
|
{
|
2017-05-12 21:30:06 +02:00
|
|
|
OWSAssert(thread);
|
2016-09-21 14:37:51 +02:00
|
|
|
self.thread = thread;
|
2017-05-12 21:30:06 +02:00
|
|
|
|
|
|
|
if ([self.thread isKindOfClass:[TSContactThread class]]) {
|
|
|
|
self.title = NSLocalizedString(
|
|
|
|
@"CONVERSATION_SETTINGS_CONTACT_INFO_TITLE", @"Navbar title when viewing settings for a 1-on-1 thread");
|
|
|
|
} else {
|
|
|
|
self.title = NSLocalizedString(
|
|
|
|
@"CONVERSATION_SETTINGS_GROUP_INFO_TITLE", @"Navbar title when viewing settings for a group thread");
|
|
|
|
}
|
|
|
|
|
2017-05-09 23:55:18 +02:00
|
|
|
[self updateEditButton];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateEditButton
|
|
|
|
{
|
|
|
|
OWSAssert(self.thread);
|
|
|
|
|
2017-05-18 14:41:28 +02:00
|
|
|
if ([self.thread isKindOfClass:[TSContactThread class]] && self.contactsManager.supportsContactEditing) {
|
2017-05-09 23:55:18 +02:00
|
|
|
self.navigationItem.rightBarButtonItem =
|
|
|
|
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"EDIT_TXT", nil)
|
|
|
|
style:UIBarButtonItemStylePlain
|
|
|
|
target:self
|
|
|
|
action:@selector(didTapEditButton)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - ContactEditingDelegate
|
|
|
|
|
|
|
|
- (void)didFinishEditingContact
|
|
|
|
{
|
|
|
|
DDLogDebug(@"%@ %s", self.tag, __PRETTY_FUNCTION__);
|
2017-05-10 18:02:14 +02:00
|
|
|
[self dismissViewControllerAnimated:NO completion:nil];
|
2017-05-09 23:55:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - CNContactViewControllerDelegate
|
|
|
|
|
|
|
|
- (void)contactViewController:(CNContactViewController *)viewController
|
|
|
|
didCompleteWithContact:(nullable CNContact *)contact
|
|
|
|
{
|
2017-05-10 18:02:14 +02:00
|
|
|
if (contact) {
|
|
|
|
// Saving normally returns you to the "Show Contact" view
|
|
|
|
// which we're not interested in, so we skip it here. There is
|
|
|
|
// an unfortunate blip of the "Show Contact" view on slower devices.
|
|
|
|
DDLogDebug(@"%@ completed editing contact.", self.tag);
|
|
|
|
[self dismissViewControllerAnimated:NO completion:nil];
|
|
|
|
} else {
|
|
|
|
DDLogDebug(@"%@ canceled editing contact.", self.tag);
|
|
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
2017-05-09 23:55:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - ContactsViewHelperDelegate
|
|
|
|
|
|
|
|
- (void)contactsViewHelperDidUpdateContacts
|
|
|
|
{
|
|
|
|
[self updateTableContents];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - View Lifecycle
|
|
|
|
|
|
|
|
- (void)viewDidLoad
|
|
|
|
{
|
|
|
|
[super viewDidLoad];
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
_disappearingMessagesDurationLabel = [UILabel new];
|
2016-09-21 14:37:51 +02:00
|
|
|
|
|
|
|
self.disappearingMessagesDurations = [OWSDisappearingMessagesConfiguration validDurationsSeconds];
|
|
|
|
|
|
|
|
self.disappearingMessagesConfiguration =
|
|
|
|
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:self.thread.uniqueId];
|
|
|
|
|
|
|
|
if (!self.disappearingMessagesConfiguration) {
|
|
|
|
self.disappearingMessagesConfiguration =
|
|
|
|
[[OWSDisappearingMessagesConfiguration alloc] initDefaultWithThreadId:self.thread.uniqueId];
|
|
|
|
}
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
[self updateTableContents];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateTableContents
|
|
|
|
{
|
|
|
|
OWSTableContents *contents = [OWSTableContents new];
|
|
|
|
contents.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen");
|
|
|
|
|
|
|
|
__weak OWSConversationSettingsTableViewController *weakSelf = self;
|
|
|
|
|
2017-04-10 21:58:34 +02:00
|
|
|
// First section.
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
OWSTableSection *firstSection = [OWSTableSection new];
|
2017-04-03 16:29:11 +02:00
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
firstSection.customHeaderView = [self firstSectionHeader];
|
|
|
|
firstSection.customHeaderHeight = @(100.f);
|
2017-04-10 21:58:34 +02:00
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
if (!self.isGroupThread && self.thread.hasSafetyNumbers) {
|
2017-04-19 17:04:25 +02:00
|
|
|
[firstSection
|
|
|
|
addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
2017-04-17 21:13:15 +02:00
|
|
|
|
2017-06-05 22:13:01 +02:00
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_lock_outline"];
|
2017-04-19 17:04:25 +02:00
|
|
|
[cell.contentView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
2017-04-19 17:04:25 +02:00
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text = NSLocalizedString(@"VERIFY_PRIVACY", @"table cell label in conversation settings");
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[cell.contentView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
2017-06-05 22:13:01 +02:00
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
2017-04-19 17:04:25 +02:00
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
actionBlock:^{
|
|
|
|
OWSConversationSettingsTableViewController *strongSelf = weakSelf;
|
|
|
|
if (!strongSelf) {
|
|
|
|
return;
|
|
|
|
}
|
2017-04-21 23:03:18 +02:00
|
|
|
FingerprintViewController *fingerprintViewController = [[UIStoryboard main]
|
|
|
|
instantiateViewControllerWithIdentifier:@"FingerprintViewController"];
|
2017-04-19 17:04:25 +02:00
|
|
|
|
|
|
|
OWSFingerprintBuilder *fingerprintBuilder =
|
|
|
|
[[OWSFingerprintBuilder alloc] initWithStorageManager:strongSelf.storageManager
|
|
|
|
contactsManager:strongSelf.contactsManager];
|
|
|
|
|
|
|
|
OWSFingerprint *fingerprint =
|
|
|
|
[fingerprintBuilder fingerprintWithTheirSignalId:strongSelf.thread.contactIdentifier];
|
|
|
|
|
2017-05-27 03:19:46 +02:00
|
|
|
[fingerprintViewController configureWithFingerprint:fingerprint
|
|
|
|
contactName:[strongSelf threadName]];
|
2017-04-19 17:04:25 +02:00
|
|
|
fingerprintViewController.dismissDelegate = strongSelf;
|
|
|
|
|
|
|
|
[strongSelf presentViewController:fingerprintViewController animated:YES completion:nil];
|
|
|
|
}]];
|
2017-04-10 21:58:34 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
[firstSection
|
|
|
|
addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
2017-04-03 16:29:11 +02:00
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
UIView *topView = [UIView new];
|
|
|
|
[cell.contentView addSubview:topView];
|
|
|
|
[topView autoPinWidthToSuperview];
|
|
|
|
[topView autoPinEdgeToSuperviewEdge:ALEdgeTop];
|
|
|
|
[topView autoSetDimension:ALDimensionHeight toSize:kOWSTable_DefaultCellHeight];
|
|
|
|
|
2017-06-05 22:13:01 +02:00
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_hourglass"];
|
2017-04-17 21:13:15 +02:00
|
|
|
[topView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text = NSLocalizedString(@"DISAPPEARING_MESSAGES", @"table cell label in conversation settings");
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[topView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
2017-06-05 22:13:01 +02:00
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
|
|
|
UISwitch *switchView = [UISwitch new];
|
|
|
|
switchView.on = self.disappearingMessagesConfiguration.isEnabled;
|
|
|
|
[switchView addTarget:self
|
|
|
|
action:@selector(disappearingMessagesSwitchValueDidChange:)
|
|
|
|
forControlEvents:UIControlEventValueChanged];
|
|
|
|
[topView addSubview:switchView];
|
|
|
|
[switchView autoVCenterInSuperview];
|
|
|
|
[switchView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *subtitleLabel = [UILabel new];
|
|
|
|
subtitleLabel.text
|
|
|
|
= NSLocalizedString(@"DISAPPEARING_MESSAGES_DESCRIPTION", @"subheading in conversation settings");
|
|
|
|
subtitleLabel.textColor = [UIColor blackColor];
|
|
|
|
subtitleLabel.font = [UIFont ows_footnoteFont];
|
|
|
|
subtitleLabel.numberOfLines = 0;
|
|
|
|
subtitleLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
|
|
[cell.contentView addSubview:subtitleLabel];
|
|
|
|
[subtitleLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:topView];
|
|
|
|
[subtitleLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:rowLabel];
|
|
|
|
[subtitleLabel autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:16.f];
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
return cell;
|
|
|
|
}
|
2017-04-17 21:13:15 +02:00
|
|
|
// TODO: We shouldn't hard-code a row height that will contain the cell content.
|
|
|
|
customRowHeight:108.f
|
|
|
|
actionBlock:nil]];
|
|
|
|
|
|
|
|
if (self.disappearingMessagesConfiguration.isEnabled) {
|
|
|
|
[firstSection
|
|
|
|
addItem:[OWSTableItem
|
|
|
|
itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
|
|
|
|
UIView *topView = [UIView new];
|
|
|
|
[cell.contentView addSubview:topView];
|
|
|
|
[topView autoPinWidthToSuperview];
|
|
|
|
[topView autoPinEdgeToSuperviewEdge:ALEdgeTop];
|
|
|
|
[topView autoSetDimension:ALDimensionHeight toSize:kOWSTable_DefaultCellHeight];
|
|
|
|
|
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_hourglass_empty"];
|
|
|
|
[topView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = self.disappearingMessagesDurationLabel;
|
|
|
|
[self updateDisappearingMessagesDurationLabel];
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_footnoteFont];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[topView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
2017-06-05 22:13:01 +02:00
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
|
|
|
UISlider *slider = [UISlider new];
|
|
|
|
slider.maximumValue = (float)(self.disappearingMessagesDurations.count - 1);
|
|
|
|
slider.minimumValue = 0;
|
|
|
|
slider.continuous = YES; // NO fires change event only once you let go
|
|
|
|
slider.value = self.disappearingMessagesConfiguration.durationIndex;
|
|
|
|
[slider addTarget:self
|
|
|
|
action:@selector(durationSliderDidChange:)
|
|
|
|
forControlEvents:UIControlEventValueChanged];
|
|
|
|
[cell.contentView addSubview:slider];
|
|
|
|
[slider autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:topView];
|
|
|
|
[slider autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:rowLabel];
|
|
|
|
[slider autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:16.f];
|
|
|
|
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
// TODO: We shouldn't hard-code a row height that will contain the cell content.
|
|
|
|
customRowHeight:84.f
|
|
|
|
actionBlock:nil]];
|
2017-04-03 16:29:11 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
[contents addSection:firstSection];
|
|
|
|
|
|
|
|
// Group settings section.
|
2017-04-03 16:29:11 +02:00
|
|
|
|
|
|
|
if (self.isGroupThread) {
|
|
|
|
NSArray *groupItems = @[
|
|
|
|
[OWSTableItem itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
2017-06-05 22:13:01 +02:00
|
|
|
|
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_group_edit"];
|
|
|
|
[cell.contentView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text = NSLocalizedString(@"EDIT_GROUP_ACTION", @"table cell label in conversation settings");
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[cell.contentView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
actionBlock:^{
|
2017-05-02 16:54:07 +02:00
|
|
|
[weakSelf showUpdateGroupView:UpdateGroupMode_Default];
|
2017-04-03 16:29:11 +02:00
|
|
|
}],
|
|
|
|
[OWSTableItem itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
2017-06-05 22:13:01 +02:00
|
|
|
|
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_group_members"];
|
|
|
|
[cell.contentView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text
|
2017-04-03 16:29:11 +02:00
|
|
|
= NSLocalizedString(@"LIST_GROUP_MEMBERS_ACTION", @"table cell label in conversation settings");
|
2017-06-05 22:13:01 +02:00
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[cell.contentView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
actionBlock:^{
|
2017-04-19 17:04:25 +02:00
|
|
|
OWSConversationSettingsTableViewController *strongSelf = weakSelf;
|
|
|
|
if (!strongSelf) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ShowGroupMembersViewController *showGroupMembersViewController =
|
2017-05-24 15:33:17 +02:00
|
|
|
[ShowGroupMembersViewController new];
|
2017-04-19 17:04:25 +02:00
|
|
|
[showGroupMembersViewController configWithThread:(TSGroupThread *)strongSelf.thread];
|
|
|
|
[strongSelf.navigationController pushViewController:showGroupMembersViewController animated:YES];
|
2017-04-03 16:29:11 +02:00
|
|
|
}],
|
2017-06-05 22:13:01 +02:00
|
|
|
[OWSTableItem itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
|
|
|
|
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_group_leave"];
|
|
|
|
[cell.contentView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text = NSLocalizedString(@"LEAVE_GROUP_ACTION", @"table cell label in conversation settings");
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[cell.contentView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
|
|
|
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
actionBlock:^{
|
|
|
|
[weakSelf didTapLeaveGroup];
|
|
|
|
}],
|
2017-04-03 16:29:11 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
[contents addSection:[OWSTableSection sectionWithTitle:NSLocalizedString(@"GROUP_MANAGEMENT_SECTION",
|
|
|
|
@"Conversation settings table section title")
|
|
|
|
items:groupItems]];
|
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
// Mute thread section.
|
|
|
|
|
|
|
|
OWSTableSection *muteSection = [OWSTableSection new];
|
|
|
|
[muteSection addItem:[OWSTableItem itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
|
|
|
|
2017-06-05 22:13:01 +02:00
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_mute_thread"];
|
2017-04-17 21:13:15 +02:00
|
|
|
[cell.contentView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text = NSLocalizedString(
|
|
|
|
@"CONVERSATION_SETTINGS_MUTE_LABEL", @"label for 'mute thread' cell in conversation settings");
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[cell.contentView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
2017-06-05 22:13:01 +02:00
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
|
|
|
NSString *muteStatus = NSLocalizedString(
|
|
|
|
@"CONVERSATION_SETTINGS_MUTE_NOT_MUTED", @"Indicates that the current thread is not muted.");
|
|
|
|
NSDate *mutedUntilDate = self.thread.mutedUntilDate;
|
|
|
|
NSDate *now = [NSDate date];
|
|
|
|
if (mutedUntilDate != nil && [mutedUntilDate timeIntervalSinceDate:now] > 0) {
|
|
|
|
NSCalendar *calendar = [NSCalendar currentCalendar];
|
|
|
|
NSCalendarUnit calendarUnits = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
|
|
|
|
NSDateComponents *muteUntilComponents = [calendar components:calendarUnits fromDate:mutedUntilDate];
|
|
|
|
NSDateComponents *nowComponents = [calendar components:calendarUnits fromDate:now];
|
|
|
|
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
|
|
|
if (nowComponents.year != muteUntilComponents.year || nowComponents.month != muteUntilComponents.month
|
|
|
|
|| nowComponents.day != muteUntilComponents.day) {
|
|
|
|
|
|
|
|
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
|
|
|
|
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
|
|
|
|
} else {
|
|
|
|
[dateFormatter setDateStyle:NSDateFormatterNoStyle];
|
|
|
|
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
|
|
|
|
}
|
|
|
|
|
|
|
|
muteStatus =
|
|
|
|
[NSString stringWithFormat:NSLocalizedString(@"CONVERSATION_SETTINGS_MUTED_UNTIL_FORMAT",
|
|
|
|
@"Indicates that this thread is muted until a given date or time. "
|
|
|
|
@"Embeds {{The date or time which the thread is muted until}}."),
|
|
|
|
[dateFormatter stringFromDate:mutedUntilDate]];
|
|
|
|
}
|
|
|
|
|
|
|
|
UILabel *statusLabel = [UILabel new];
|
|
|
|
statusLabel.textColor = [UIColor colorWithWhite:0.5f alpha:1.f];
|
|
|
|
statusLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
statusLabel.text = muteStatus;
|
|
|
|
[cell.contentView addSubview:statusLabel];
|
|
|
|
[statusLabel autoVCenterInSuperview];
|
|
|
|
[statusLabel autoPinEdgeToSuperviewEdge:ALEdgeRight];
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
customRowHeight:45.f
|
|
|
|
actionBlock:^{
|
|
|
|
[weakSelf showMuteUnmuteActionSheet];
|
|
|
|
}]];
|
|
|
|
muteSection.footerTitle
|
|
|
|
= NSLocalizedString(@"MUTE_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of muting a thread.");
|
|
|
|
[contents addSection:muteSection];
|
|
|
|
|
|
|
|
// Block user section.
|
|
|
|
|
|
|
|
if (!self.isGroupThread) {
|
|
|
|
BOOL isBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.thread.contactIdentifier];
|
|
|
|
|
|
|
|
OWSTableItem *item = [OWSTableItem itemWithCustomCellBlock:^{
|
|
|
|
UITableViewCell *cell = [UITableViewCell new];
|
|
|
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
|
2017-06-05 22:13:01 +02:00
|
|
|
UIImageView *iconView = [self viewForIconWithName:@"table_ic_block"];
|
2017-04-17 21:13:15 +02:00
|
|
|
[cell.contentView addSubview:iconView];
|
|
|
|
[iconView autoVCenterInSuperview];
|
|
|
|
[iconView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *rowLabel = [UILabel new];
|
|
|
|
rowLabel.text = NSLocalizedString(
|
|
|
|
@"CONVERSATION_SETTINGS_BLOCK_THIS_USER", @"table cell label in conversation settings");
|
|
|
|
rowLabel.textColor = [UIColor blackColor];
|
|
|
|
rowLabel.font = [UIFont ows_regularFontWithSize:17.f];
|
|
|
|
rowLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[cell.contentView addSubview:rowLabel];
|
|
|
|
[rowLabel autoVCenterInSuperview];
|
2017-06-05 22:13:01 +02:00
|
|
|
[rowLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:iconView withOffset:12.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
|
|
|
UISwitch *blockUserSwitch = [UISwitch new];
|
|
|
|
blockUserSwitch.on = isBlocked;
|
|
|
|
[blockUserSwitch addTarget:self
|
|
|
|
action:@selector(blockUserSwitchDidChange:)
|
|
|
|
forControlEvents:UIControlEventValueChanged];
|
|
|
|
cell.accessoryView = blockUserSwitch;
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
actionBlock:nil];
|
|
|
|
OWSTableSection *section = [OWSTableSection sectionWithTitle:nil
|
|
|
|
items:@[
|
|
|
|
item,
|
|
|
|
]];
|
|
|
|
section.footerTitle = NSLocalizedString(
|
|
|
|
@"BLOCK_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of blocking another user.");
|
|
|
|
[contents addSection:section];
|
|
|
|
}
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
self.contents = contents;
|
|
|
|
[self.tableView reloadData];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
- (UIView *)firstSectionHeader
|
|
|
|
{
|
|
|
|
UIView *firstSectionHeader = [UIView new];
|
|
|
|
UIView *threadInfoView = [UIView new];
|
|
|
|
[firstSectionHeader addSubview:threadInfoView];
|
|
|
|
[threadInfoView autoPinWidthToSuperviewWithMargin:16.f];
|
|
|
|
[threadInfoView autoPinHeightToSuperviewWithMargin:16.f];
|
|
|
|
|
2017-05-27 17:56:08 +02:00
|
|
|
const NSUInteger kAvatarSize = 68;
|
|
|
|
UIImage *avatar =
|
|
|
|
[OWSAvatarBuilder buildImageForThread:self.thread contactsManager:self.contactsManager diameter:kAvatarSize];
|
2017-04-17 21:13:15 +02:00
|
|
|
OWSAssert(avatar);
|
2017-05-27 17:56:08 +02:00
|
|
|
|
2017-05-13 23:36:12 +02:00
|
|
|
AvatarImageView *avatarView = [[AvatarImageView alloc] initWithImage:avatar];
|
2017-04-21 21:37:51 +02:00
|
|
|
_avatarView = avatarView;
|
2017-04-17 21:13:15 +02:00
|
|
|
[threadInfoView addSubview:avatarView];
|
|
|
|
[avatarView autoVCenterInSuperview];
|
|
|
|
[avatarView autoPinEdgeToSuperviewEdge:ALEdgeLeft];
|
|
|
|
[avatarView autoSetDimension:ALDimensionWidth toSize:kAvatarSize];
|
|
|
|
[avatarView autoSetDimension:ALDimensionHeight toSize:kAvatarSize];
|
|
|
|
|
|
|
|
UIView *threadNameView = [UIView new];
|
|
|
|
[threadInfoView addSubview:threadNameView];
|
|
|
|
[threadNameView autoVCenterInSuperview];
|
|
|
|
[threadNameView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:avatarView withOffset:16.f];
|
|
|
|
[threadNameView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:16.f];
|
|
|
|
|
|
|
|
UILabel *threadTitleLabel = [UILabel new];
|
|
|
|
threadTitleLabel.text = self.threadName;
|
|
|
|
threadTitleLabel.textColor = [UIColor blackColor];
|
|
|
|
threadTitleLabel.font = [UIFont ows_dynamicTypeTitle2Font];
|
|
|
|
threadTitleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[threadNameView addSubview:threadTitleLabel];
|
|
|
|
[threadTitleLabel autoPinEdgeToSuperviewEdge:ALEdgeTop];
|
|
|
|
[threadTitleLabel autoPinEdgeToSuperviewEdge:ALEdgeLeft];
|
2017-05-10 00:05:53 +02:00
|
|
|
[threadTitleLabel autoPinEdgeToSuperviewEdge:ALEdgeRight];
|
2017-04-17 21:13:15 +02:00
|
|
|
|
|
|
|
if (![self isGroupThread] && ![self.thread.name isEqualToString:self.thread.contactIdentifier]) {
|
|
|
|
NSString *subtitle =
|
|
|
|
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:self.thread.contactIdentifier];
|
|
|
|
|
|
|
|
UILabel *threadSubtitleLabel = [UILabel new];
|
|
|
|
threadSubtitleLabel.text = subtitle;
|
|
|
|
threadSubtitleLabel.textColor = [UIColor blackColor];
|
|
|
|
// TODO:
|
|
|
|
threadSubtitleLabel.font = [UIFont ows_regularFontWithSize:12.f];
|
|
|
|
threadSubtitleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
|
|
[threadNameView addSubview:threadSubtitleLabel];
|
|
|
|
[threadSubtitleLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
|
|
|
[threadSubtitleLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:threadTitleLabel];
|
|
|
|
[threadSubtitleLabel autoPinEdgeToSuperviewEdge:ALEdgeLeft];
|
|
|
|
} else {
|
|
|
|
[threadTitleLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
|
|
|
}
|
|
|
|
|
2017-04-21 21:37:51 +02:00
|
|
|
[firstSectionHeader
|
2017-05-02 18:30:53 +02:00
|
|
|
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
|
|
|
|
action:@selector(conversationNameTouched:)]];
|
2017-04-21 21:37:51 +02:00
|
|
|
firstSectionHeader.userInteractionEnabled = YES;
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
return firstSectionHeader;
|
|
|
|
}
|
|
|
|
|
2017-04-21 21:37:51 +02:00
|
|
|
- (void)conversationNameTouched:(UIGestureRecognizer *)sender
|
|
|
|
{
|
2017-04-28 18:18:42 +02:00
|
|
|
if (sender.state == UIGestureRecognizerStateRecognized) {
|
2017-04-21 21:37:51 +02:00
|
|
|
if (self.isGroupThread) {
|
|
|
|
CGPoint location = [sender locationInView:self.avatarView];
|
|
|
|
if (CGRectContainsPoint(self.avatarView.bounds, location)) {
|
2017-05-02 16:54:07 +02:00
|
|
|
[self showUpdateGroupView:UpdateGroupMode_EditGroupAvatar];
|
2017-04-21 21:37:51 +02:00
|
|
|
} else {
|
2017-05-02 16:54:07 +02:00
|
|
|
[self showUpdateGroupView:UpdateGroupMode_EditGroupName];
|
2017-04-21 21:37:51 +02:00
|
|
|
}
|
|
|
|
} else {
|
2017-05-18 16:04:13 +02:00
|
|
|
if (self.contactsManager.supportsContactEditing) {
|
|
|
|
[self presentContactViewController];
|
|
|
|
}
|
2017-04-21 21:37:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
- (UIImageView *)viewForIconWithName:(NSString *)iconName
|
|
|
|
{
|
|
|
|
UIImage *icon = [UIImage imageNamed:iconName];
|
|
|
|
OWSAssert(icon);
|
|
|
|
UIImageView *iconView = [UIImageView new];
|
|
|
|
iconView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
2017-05-16 22:40:40 +02:00
|
|
|
iconView.tintColor = [UIColor colorWithRGBHex:0x505050];
|
2017-04-17 21:13:15 +02:00
|
|
|
iconView.contentMode = UIViewContentModeScaleToFill;
|
2017-06-05 22:13:01 +02:00
|
|
|
[iconView autoSetDimension:ALDimensionWidth toSize:24.f];
|
|
|
|
[iconView autoSetDimension:ALDimensionHeight toSize:24.f];
|
2017-04-17 21:13:15 +02:00
|
|
|
return iconView;
|
|
|
|
}
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
- (void)viewWillAppear:(BOOL)animated
|
|
|
|
{
|
|
|
|
[super viewWillAppear:animated];
|
2017-03-19 20:11:57 +01:00
|
|
|
|
2017-05-09 23:55:18 +02:00
|
|
|
// In case we're dismissing a CNContactViewController which requires default system appearance
|
|
|
|
[UIUtil applySignalAppearence];
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
// HACK to unselect rows when swiping back
|
|
|
|
// http://stackoverflow.com/questions/19379510/uitableviewcell-doesnt-get-deselected-when-swiping-back-quickly
|
|
|
|
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewWillDisappear:(BOOL)animated
|
|
|
|
{
|
|
|
|
[super viewWillDisappear:animated];
|
|
|
|
|
|
|
|
if (self.disappearingMessagesConfiguration.isNewRecord && !self.disappearingMessagesConfiguration.isEnabled) {
|
|
|
|
// don't save defaults, else we'll unintentionally save the configuration and notify the contact.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.disappearingMessagesConfiguration.dictionaryValueDidChange) {
|
|
|
|
[self.disappearingMessagesConfiguration save];
|
|
|
|
OWSDisappearingConfigurationUpdateInfoMessage *infoMessage =
|
|
|
|
[[OWSDisappearingConfigurationUpdateInfoMessage alloc]
|
|
|
|
initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
|
|
|
thread:self.thread
|
|
|
|
configuration:self.disappearingMessagesConfiguration];
|
|
|
|
[infoMessage save];
|
|
|
|
|
|
|
|
[OWSNotifyRemoteOfUpdatedDisappearingConfigurationJob
|
|
|
|
runWithConfiguration:self.disappearingMessagesConfiguration
|
|
|
|
thread:self.thread
|
2016-10-14 22:59:58 +02:00
|
|
|
messageSender:self.messageSender];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Actions
|
|
|
|
|
2017-05-02 16:54:07 +02:00
|
|
|
- (void)showUpdateGroupView:(UpdateGroupMode)mode
|
|
|
|
{
|
|
|
|
OWSAssert(self.conversationSettingsViewDelegate);
|
|
|
|
|
|
|
|
UpdateGroupViewController *updateGroupViewController = [UpdateGroupViewController new];
|
|
|
|
updateGroupViewController.conversationSettingsViewDelegate = self.conversationSettingsViewDelegate;
|
|
|
|
updateGroupViewController.thread = (TSGroupThread *)self.thread;
|
|
|
|
updateGroupViewController.mode = mode;
|
|
|
|
|
|
|
|
UINavigationController *navigationController =
|
|
|
|
[[UINavigationController alloc] initWithRootViewController:updateGroupViewController];
|
|
|
|
[self presentViewController:navigationController animated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
2017-05-10 18:07:14 +02:00
|
|
|
- (void)presentContactViewController
|
|
|
|
{
|
2017-05-18 14:41:28 +02:00
|
|
|
if (!self.contactsManager.supportsContactEditing) {
|
2017-05-18 16:04:13 +02:00
|
|
|
DDLogError(@"%@ Contact editing not supported", self.tag);
|
|
|
|
OWSAssert(NO);
|
2017-05-18 14:41:28 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-05-10 18:07:14 +02:00
|
|
|
if (![self.thread isKindOfClass:[TSContactThread class]]) {
|
|
|
|
DDLogError(@"%@ unexpected thread: %@ in %s", self.tag, self.thread, __PRETTY_FUNCTION__);
|
|
|
|
OWSAssert(NO);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TSContactThread *contactThread = (TSContactThread *)self.thread;
|
|
|
|
[self.contactsViewHelper presentContactViewControllerForRecipientId:contactThread.contactIdentifier
|
|
|
|
fromViewController:self
|
|
|
|
editImmediately:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)didTapEditButton
|
|
|
|
{
|
|
|
|
[self presentContactViewController];
|
|
|
|
}
|
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
- (void)didTapLeaveGroup
|
|
|
|
{
|
|
|
|
UIAlertController *alertController =
|
|
|
|
[UIAlertController alertControllerWithTitle:NSLocalizedString(@"CONFIRM_LEAVE_GROUP_TITLE", @"Alert title")
|
|
|
|
message:NSLocalizedString(@"CONFIRM_LEAVE_GROUP_DESCRIPTION", @"Alert body")
|
|
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
|
|
|
|
UIAlertAction *leaveAction = [UIAlertAction
|
|
|
|
actionWithTitle:NSLocalizedString(@"LEAVE_BUTTON_TITLE", @"Confirmation button within contextual alert")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull action) {
|
|
|
|
[self leaveGroup];
|
|
|
|
}];
|
|
|
|
[alertController addAction:leaveAction];
|
|
|
|
|
|
|
|
UIAlertAction *cancelAction = [UIAlertAction
|
|
|
|
actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
|
|
|
|
style:UIAlertActionStyleCancel
|
|
|
|
handler:^(UIAlertAction *_Nonnull action) {
|
|
|
|
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
|
|
|
|
}];
|
|
|
|
[alertController addAction:cancelAction];
|
|
|
|
|
|
|
|
[self presentViewController:alertController animated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)leaveGroup
|
|
|
|
{
|
|
|
|
TSGroupThread *gThread = (TSGroupThread *)self.thread;
|
|
|
|
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
|
|
|
inThread:gThread
|
2017-04-12 17:03:16 +02:00
|
|
|
groupMetaMessage:TSGroupMessageQuit];
|
2016-10-14 22:59:58 +02:00
|
|
|
[self.messageSender sendMessage:message
|
2016-09-21 14:37:51 +02:00
|
|
|
success:^{
|
|
|
|
DDLogInfo(@"%@ Successfully left group.", self.tag);
|
|
|
|
}
|
2016-10-14 22:59:58 +02:00
|
|
|
failure:^(NSError *error) {
|
|
|
|
DDLogWarn(@"%@ Failed to leave group with error: %@", self.tag, error);
|
2016-09-21 14:37:51 +02:00
|
|
|
}];
|
|
|
|
|
|
|
|
NSMutableArray *newGroupMemberIds = [NSMutableArray arrayWithArray:gThread.groupModel.groupMemberIds];
|
|
|
|
[newGroupMemberIds removeObject:[self.storageManager localNumber]];
|
|
|
|
gThread.groupModel.groupMemberIds = newGroupMemberIds;
|
|
|
|
[gThread save];
|
|
|
|
|
|
|
|
[self.navigationController popViewControllerAnimated:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)presentedModalWasDismissed
|
|
|
|
{
|
|
|
|
// Else row stays selected after dismissing modal.
|
|
|
|
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
|
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
- (void)disappearingMessagesSwitchValueDidChange:(UISwitch *)sender
|
2016-09-21 14:37:51 +02:00
|
|
|
{
|
|
|
|
UISwitch *disappearingMessagesSwitch = (UISwitch *)sender;
|
2017-04-17 21:13:15 +02:00
|
|
|
|
2016-09-21 14:37:51 +02:00
|
|
|
[self toggleDisappearingMessages:disappearingMessagesSwitch.isOn];
|
2017-04-03 16:29:11 +02:00
|
|
|
|
|
|
|
[self updateTableContents];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
- (void)blockUserSwitchDidChange:(id)sender
|
2016-09-21 14:37:51 +02:00
|
|
|
{
|
2017-04-03 16:29:11 +02:00
|
|
|
OWSAssert(!self.isGroupThread);
|
2016-09-21 14:37:51 +02:00
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
if (![sender isKindOfClass:[UISwitch class]]) {
|
|
|
|
DDLogError(@"%@ Unexpected sender for block user switch: %@", self.tag, sender);
|
2017-04-05 15:09:09 +02:00
|
|
|
OWSAssert(0);
|
2017-04-03 16:29:11 +02:00
|
|
|
}
|
|
|
|
UISwitch *blockUserSwitch = (UISwitch *)sender;
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
BOOL isCurrentlyBlocked = [[_blockingManager blockedPhoneNumbers] containsObject:self.thread.contactIdentifier];
|
2016-09-21 14:37:51 +02:00
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
if (blockUserSwitch.isOn) {
|
|
|
|
OWSAssert(!isCurrentlyBlocked);
|
|
|
|
if (isCurrentlyBlocked) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
[BlockListUIUtils showBlockPhoneNumberActionSheet:self.thread.contactIdentifier
|
|
|
|
fromViewController:self
|
|
|
|
blockingManager:_blockingManager
|
2017-04-04 16:19:47 +02:00
|
|
|
contactsManager:_contactsManager
|
2017-04-03 16:29:11 +02:00
|
|
|
completionBlock:^(BOOL isBlocked) {
|
|
|
|
// Update switch state if user cancels action.
|
|
|
|
blockUserSwitch.on = isBlocked;
|
|
|
|
}];
|
2016-09-21 14:37:51 +02:00
|
|
|
} else {
|
2017-04-03 16:29:11 +02:00
|
|
|
OWSAssert(isCurrentlyBlocked);
|
|
|
|
if (!isCurrentlyBlocked) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
[BlockListUIUtils showUnblockPhoneNumberActionSheet:self.thread.contactIdentifier
|
|
|
|
fromViewController:self
|
|
|
|
blockingManager:_blockingManager
|
2017-04-04 16:19:47 +02:00
|
|
|
contactsManager:_contactsManager
|
2017-04-03 16:29:11 +02:00
|
|
|
completionBlock:^(BOOL isBlocked) {
|
|
|
|
// Update switch state if user cancels action.
|
|
|
|
blockUserSwitch.on = isBlocked;
|
|
|
|
}];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-03 16:29:11 +02:00
|
|
|
- (void)toggleDisappearingMessages:(BOOL)flag
|
2016-09-21 14:37:51 +02:00
|
|
|
{
|
2017-04-03 16:29:11 +02:00
|
|
|
self.disappearingMessagesConfiguration.enabled = flag;
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
[self.tableView reloadData];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
- (void)durationSliderDidChange:(UISlider *)slider
|
2016-09-21 14:37:51 +02:00
|
|
|
{
|
|
|
|
// snap the slider to a valid value
|
|
|
|
NSUInteger index = (NSUInteger)(slider.value + 0.5);
|
|
|
|
[slider setValue:index animated:YES];
|
|
|
|
NSNumber *numberOfSeconds = self.disappearingMessagesDurations[index];
|
|
|
|
self.disappearingMessagesConfiguration.durationSeconds = [numberOfSeconds unsignedIntValue];
|
|
|
|
|
2017-04-17 21:13:15 +02:00
|
|
|
[self updateDisappearingMessagesDurationLabel];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateDisappearingMessagesDurationLabel
|
|
|
|
{
|
2016-09-21 14:37:51 +02:00
|
|
|
if (self.disappearingMessagesConfiguration.isEnabled) {
|
|
|
|
NSString *keepForFormat = NSLocalizedString(@"KEEP_MESSAGES_DURATION",
|
|
|
|
@"Slider label embeds {{TIME_AMOUNT}}, e.g. '2 hours'. See *_TIME_AMOUNT strings for examples.");
|
|
|
|
self.disappearingMessagesDurationLabel.text =
|
|
|
|
[NSString stringWithFormat:keepForFormat, self.disappearingMessagesConfiguration.durationString];
|
|
|
|
} else {
|
|
|
|
self.disappearingMessagesDurationLabel.text
|
|
|
|
= NSLocalizedString(@"KEEP_MESSAGES_FOREVER", @"Slider label when disappearing messages is off");
|
|
|
|
}
|
2017-04-17 21:13:15 +02:00
|
|
|
|
|
|
|
[self.disappearingMessagesDurationLabel setNeedsLayout];
|
|
|
|
[self.disappearingMessagesDurationLabel.superview setNeedsLayout];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)showMuteUnmuteActionSheet
|
|
|
|
{
|
2017-04-18 18:41:56 +02:00
|
|
|
// The "unmute" action sheet has no title or message; the
|
|
|
|
// action label speaks for itself.
|
|
|
|
NSString *title = nil;
|
2017-04-17 21:13:15 +02:00
|
|
|
NSString *message = nil;
|
2017-04-18 18:41:56 +02:00
|
|
|
if (!self.thread.isMuted) {
|
2017-04-17 21:13:15 +02:00
|
|
|
title = NSLocalizedString(
|
|
|
|
@"CONVERSATION_SETTINGS_MUTE_ACTION_SHEET_TITLE", @"Title of the 'mute this thread' action sheet.");
|
|
|
|
message = NSLocalizedString(
|
|
|
|
@"MUTE_BEHAVIOR_EXPLANATION", @"An explanation of the consequences of muting a thread.");
|
|
|
|
}
|
|
|
|
|
|
|
|
UIAlertController *actionSheetController =
|
|
|
|
[UIAlertController alertControllerWithTitle:title
|
|
|
|
message:message
|
|
|
|
preferredStyle:UIAlertControllerStyleActionSheet];
|
|
|
|
|
|
|
|
__weak OWSConversationSettingsTableViewController *weakSelf = self;
|
|
|
|
if (self.thread.isMuted) {
|
|
|
|
UIAlertAction *action = [UIAlertAction actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_UNMUTE_ACTION",
|
|
|
|
@"Label for button to unmute a thread.")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull ignore) {
|
|
|
|
[weakSelf setThreadMutedUntilDate:nil];
|
|
|
|
}];
|
|
|
|
[actionSheetController addAction:action];
|
|
|
|
} else {
|
|
|
|
#ifdef DEBUG
|
|
|
|
[actionSheetController
|
|
|
|
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_MUTE_ONE_MINUTE_ACTION",
|
|
|
|
@"Label for button to mute a thread for a minute.")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull ignore) {
|
|
|
|
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
|
|
|
NSCalendar *calendar = [NSCalendar currentCalendar];
|
|
|
|
[calendar setTimeZone:timeZone];
|
|
|
|
NSDateComponents *dateComponents = [NSDateComponents new];
|
|
|
|
[dateComponents setMinute:1];
|
|
|
|
NSDate *mutedUntilDate =
|
|
|
|
[calendar dateByAddingComponents:dateComponents
|
|
|
|
toDate:[NSDate date]
|
|
|
|
options:0];
|
|
|
|
[weakSelf setThreadMutedUntilDate:mutedUntilDate];
|
|
|
|
}]];
|
|
|
|
#endif
|
|
|
|
[actionSheetController
|
|
|
|
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_MUTE_ONE_HOUR_ACTION",
|
|
|
|
@"Label for button to mute a thread for a hour.")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull ignore) {
|
|
|
|
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
|
|
|
NSCalendar *calendar = [NSCalendar currentCalendar];
|
|
|
|
[calendar setTimeZone:timeZone];
|
|
|
|
NSDateComponents *dateComponents = [NSDateComponents new];
|
|
|
|
[dateComponents setHour:1];
|
|
|
|
NSDate *mutedUntilDate =
|
|
|
|
[calendar dateByAddingComponents:dateComponents
|
|
|
|
toDate:[NSDate date]
|
|
|
|
options:0];
|
|
|
|
[weakSelf setThreadMutedUntilDate:mutedUntilDate];
|
|
|
|
}]];
|
|
|
|
[actionSheetController
|
|
|
|
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_MUTE_ONE_DAY_ACTION",
|
|
|
|
@"Label for button to mute a thread for a day.")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull ignore) {
|
|
|
|
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
|
|
|
NSCalendar *calendar = [NSCalendar currentCalendar];
|
|
|
|
[calendar setTimeZone:timeZone];
|
|
|
|
NSDateComponents *dateComponents = [NSDateComponents new];
|
|
|
|
[dateComponents setDay:1];
|
|
|
|
NSDate *mutedUntilDate =
|
|
|
|
[calendar dateByAddingComponents:dateComponents
|
|
|
|
toDate:[NSDate date]
|
|
|
|
options:0];
|
|
|
|
[weakSelf setThreadMutedUntilDate:mutedUntilDate];
|
|
|
|
}]];
|
|
|
|
[actionSheetController
|
|
|
|
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_MUTE_ONE_WEEK_ACTION",
|
|
|
|
@"Label for button to mute a thread for a week.")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull ignore) {
|
|
|
|
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
|
|
|
NSCalendar *calendar = [NSCalendar currentCalendar];
|
|
|
|
[calendar setTimeZone:timeZone];
|
|
|
|
NSDateComponents *dateComponents = [NSDateComponents new];
|
|
|
|
[dateComponents setDay:7];
|
|
|
|
NSDate *mutedUntilDate =
|
|
|
|
[calendar dateByAddingComponents:dateComponents
|
|
|
|
toDate:[NSDate date]
|
|
|
|
options:0];
|
|
|
|
[weakSelf setThreadMutedUntilDate:mutedUntilDate];
|
|
|
|
}]];
|
|
|
|
[actionSheetController
|
|
|
|
addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"CONVERSATION_SETTINGS_MUTE_ONE_YEAR_ACTION",
|
|
|
|
@"Label for button to mute a thread for a year.")
|
|
|
|
style:UIAlertActionStyleDestructive
|
|
|
|
handler:^(UIAlertAction *_Nonnull ignore) {
|
|
|
|
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
|
|
|
NSCalendar *calendar = [NSCalendar currentCalendar];
|
|
|
|
[calendar setTimeZone:timeZone];
|
|
|
|
NSDateComponents *dateComponents = [NSDateComponents new];
|
|
|
|
[dateComponents setYear:1];
|
|
|
|
NSDate *mutedUntilDate =
|
|
|
|
[calendar dateByAddingComponents:dateComponents
|
|
|
|
toDate:[NSDate date]
|
|
|
|
options:0];
|
|
|
|
[weakSelf setThreadMutedUntilDate:mutedUntilDate];
|
|
|
|
}]];
|
|
|
|
}
|
|
|
|
|
|
|
|
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
|
|
|
style:UIAlertActionStyleCancel
|
|
|
|
handler:nil];
|
|
|
|
[actionSheetController addAction:dismissAction];
|
|
|
|
|
|
|
|
[self presentViewController:actionSheetController animated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setThreadMutedUntilDate:(nullable NSDate *)value
|
|
|
|
{
|
|
|
|
[self.thread updateWithMutedUntilDate:value];
|
|
|
|
[self.tableView reloadData];
|
2016-09-21 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Logging
|
|
|
|
|
|
|
|
+ (NSString *)tag
|
|
|
|
{
|
|
|
|
return [NSString stringWithFormat:@"[%@]", self.class];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)tag
|
|
|
|
{
|
|
|
|
return self.class.tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
NS_ASSUME_NONNULL_END
|