2017-02-17 23:30:49 +01:00
//
2019-01-04 15:19:41 +01:00
// Copyright ( c ) 2019 Open Whisper Systems . All rights reserved .
2017-02-17 23:30:49 +01:00
//
2016-09-21 14:37:51 +02:00
2017-08-01 22:16:33 +02:00
# import "OWSConversationSettingsViewController.h"
2017-04-03 16:29:11 +02:00
# import "OWSBlockingManager.h"
2018-02-22 04:31:55 +01:00
# import "OWSSoundSettingsViewController.h"
2019-05-02 23:58:48 +02:00
# import "Session-Swift.h"
2016-10-06 15:44:25 +02:00
# import "UIFont+OWS.h"
2017-04-17 21:13:15 +02:00
# import "UIView+OWS.h"
2020-11-11 07:45:50 +01:00
# import < Curve25519Kit / Curve25519 . h >
2020-11-12 00:41:45 +01:00
# import < SignalCoreKit / NSDate + OWS . h >
2020-11-26 00:37:56 +01:00
# import < SessionMessagingKit / Environment . h >
2020-11-11 07:45:50 +01:00
# import < SignalUtilitiesKit / OWSProfileManager . h >
2020-11-26 00:37:56 +01:00
# import < SessionMessagingKit / OWSSounds . h >
2020-11-11 07:45:50 +01:00
# import < SignalUtilitiesKit / SignalUtilitiesKit - Swift . h >
# import < SignalUtilitiesKit / UIUtil . h >
2020-11-26 00:37:56 +01:00
# import < SessionMessagingKit / OWSDisappearingConfigurationUpdateInfoMessage . h >
2020-11-25 06:15:16 +01:00
# import < SessionMessagingKit / OWSDisappearingMessagesConfiguration . h >
# import < SessionMessagingKit / OWSPrimaryStorage . h >
# import < SessionMessagingKit / TSGroupThread . h >
# import < SessionMessagingKit / TSOutgoingMessage . h >
# import < SessionMessagingKit / TSThread . h >
2016-09-21 14:37:51 +02:00
2017-05-09 23:55:18 +02:00
@ import ContactsUI ;
2020-09-25 05:41:35 +02:00
@ import PromiseKit ;
2017-05-09 23:55:18 +02:00
2016-09-21 14:37:51 +02:00
NS_ASSUME _NONNULL _BEGIN
2021-02-18 06:49:48 +01:00
CGFloat kIconViewLength = 24 ;
2018-10-09 22:06:23 +02:00
2021-02-18 06:49:48 +01:00
@ interface OWSConversationSettingsViewController ( ) < OWSSheetViewControllerDelegate >
2016-09-21 14:37:51 +02:00
@ property ( nonatomic ) TSThread * thread ;
2018-03-19 17:22:39 +01:00
@ property ( nonatomic ) YapDatabaseConnection * uiDatabaseConnection ;
2018-06-28 19:28:14 +02:00
@ property ( nonatomic , readonly ) YapDatabaseConnection * editingDatabaseConnection ;
2016-09-21 14:37:51 +02:00
@ property ( nonatomic ) NSArray < NSNumber * > * disappearingMessagesDurations ;
@ property ( nonatomic ) OWSDisappearingMessagesConfiguration * disappearingMessagesConfiguration ;
2018-11-15 01:53:58 +01:00
@ property ( nullable , nonatomic ) MediaGallery * mediaGallery ;
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 ;
2021-03-01 03:15:54 +01:00
@ property ( nonatomic ) UILabel * displayNameLabel ;
@ property ( nonatomic ) SNTextField * displayNameTextField ;
@ property ( nonatomic ) UIView * displayNameContainer ;
@ property ( nonatomic ) BOOL isEditingDisplayName ;
2017-04-17 21:13:15 +02:00
2016-09-21 14:37:51 +02:00
@ end
2017-04-17 21:13:15 +02:00
# pragma mark -
2017-08-01 22:16:33 +02:00
@ implementation OWSConversationSettingsViewController
2016-09-21 14:37:51 +02:00
- ( 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 ;
}
2017-08-01 22:16:33 +02:00
- ( instancetype ) initWithNibName : ( nullable NSString * ) nibNameOrNil bundle : ( nullable NSBundle * ) nibBundleOrNil
{
2017-03-10 14:59:59 +01:00
self = [ super initWithNibName : nibNameOrNil bundle : nibBundleOrNil ] ;
if ( ! self ) {
return self ;
}
2017-08-01 22:16:33 +02:00
2017-03-10 14:59:59 +01:00
[ self commonInit ] ;
2017-08-01 22:16:33 +02:00
2017-03-10 14:59:59 +01:00
return self ;
}
- ( void ) commonInit
{
2017-06-09 22:21:59 +02:00
[ self observeNotifications ] ;
}
- ( void ) dealloc
{
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
}
2018-10-20 19:51:48 +02:00
# pragma mark - Dependencies
2018-12-21 19:03:09 +01:00
- ( TSAccountManager * ) tsAccountManager
{
OWSAssertDebug ( SSKEnvironment . shared . tsAccountManager ) ;
return SSKEnvironment . shared . tsAccountManager ;
}
- ( OWSBlockingManager * ) blockingManager
{
return [ OWSBlockingManager sharedManager ] ;
}
- ( OWSProfileManager * ) profileManager
{
return [ OWSProfileManager sharedManager ] ;
}
2018-10-20 19:51:48 +02:00
# pragma mark
2017-06-09 22:21:59 +02:00
- ( void ) observeNotifications
{
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( identityStateDidChange : )
name : kNSNotificationName_IdentityStateDidChange
object : nil ] ;
2017-08-23 23:09:43 +02:00
[ [ NSNotificationCenter defaultCenter ] addObserver : self
selector : @ selector ( otherUsersProfileDidChange : )
name : kNSNotificationName_OtherUsersProfileDidChange
object : nil ] ;
2016-09-21 14:37:51 +02:00
}
2018-06-28 19:28:14 +02:00
- ( YapDatabaseConnection * ) editingDatabaseConnection
{
return [ OWSPrimaryStorage sharedManager ] . dbReadWriteConnection ;
}
2020-10-29 06:13:16 +01:00
- ( nullable NSString * ) threadName
2017-04-17 21:13:15 +02:00
{
NSString * threadName = self . thread . name ;
2021-05-05 01:53:18 +02:00
if ( [ self . thread isKindOfClass : TSContactThread . class ] ) {
TSContactThread * thread = ( TSContactThread * ) self . thread ;
2021-05-05 02:00:39 +02:00
return [ [ LKStorage . shared getContactWithSessionID : thread . contactSessionID ] displayNameFor : SNContactContextRegular ] ? : @ "Anonymous" ;
2017-04-17 21:13:15 +02:00
} else if ( threadName . length = = 0 && [ self isGroupThread ] ) {
2017-10-14 19:20:46 +02:00
threadName = [ MessageStrings newGroupDefaultTitle ] ;
2017-04-17 21:13:15 +02:00
}
return threadName ;
}
- ( BOOL ) isGroupThread
{
return [ self . thread isKindOfClass : [ TSGroupThread class ] ] ;
}
2020-11-16 00:34:47 +01:00
- ( BOOL ) isOpenGroup
2020-08-13 07:08:26 +02:00
{
2020-08-18 05:58:24 +02:00
if ( [ self isGroupThread ] ) {
TSGroupThread * thread = ( TSGroupThread * ) self . thread ;
2020-11-16 00:34:47 +01:00
return thread . isOpenGroup ;
2020-08-18 05:58:24 +02:00
}
return false ;
2020-08-13 07:08:26 +02:00
}
2020-11-16 00:34:47 +01:00
- ( BOOL ) isClosedGroup
2020-01-13 01:14:49 +01:00
{
if ( self . isGroupThread ) {
2020-01-28 05:08:42 +01:00
TSGroupThread * thread = ( TSGroupThread * ) self . thread ;
2020-11-16 00:34:47 +01:00
return thread . groupModel . groupType = = closedGroup ;
2020-01-13 01:14:49 +01:00
}
2020-01-28 05:08:42 +01:00
return false ;
2020-01-13 01:14:49 +01:00
}
2018-03-19 17:22:39 +01:00
- ( void ) configureWithThread : ( TSThread * ) thread uiDatabaseConnection : ( YapDatabaseConnection * ) uiDatabaseConnection
2016-09-21 14:37:51 +02:00
{
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( thread ) ;
2016-09-21 14:37:51 +02:00
self . thread = thread ;
2018-03-19 17:22:39 +01:00
self . uiDatabaseConnection = uiDatabaseConnection ;
2017-07-04 22:40:28 +02:00
}
2017-05-09 23:55:18 +02:00
# pragma mark - ContactEditingDelegate
- ( void ) didFinishEditingContact
{
2017-07-04 22:40:28 +02:00
[ self updateTableContents ] ;
2018-08-27 18:09:39 +02:00
OWSLogDebug ( @ "" ) ;
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-07-04 22:40:28 +02:00
[ self updateTableContents ] ;
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 .
2018-08-27 18:51:32 +02:00
OWSLogDebug ( @ "completed editing contact." ) ;
2017-05-10 18:02:14 +02:00
[ self dismissViewControllerAnimated : NO completion : nil ] ;
} else {
2018-08-27 18:51:32 +02:00
OWSLogDebug ( @ "canceled editing contact." ) ;
2017-05-10 18:02:14 +02:00
[ self dismissViewControllerAnimated : YES completion : nil ] ;
}
2017-05-09 23:55:18 +02:00
}
2016-09-21 14:37:51 +02:00
# pragma mark - View Lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ] ;
2021-03-01 03:15:54 +01:00
self . displayNameLabel = [ UILabel new ] ;
self . displayNameLabel . textColor = LKColors . text ;
self . displayNameLabel . font = [ UIFont boldSystemFontOfSize : LKValues . largeFontSize ] ;
self . displayNameLabel . lineBreakMode = NSLineBreakByTruncatingTail ;
self . displayNameLabel . textAlignment = NSTextAlignmentCenter ;
self . displayNameTextField = [ [ SNTextField alloc ] initWithPlaceholder : @ "Enter a name" usesDefaultHeight : NO ] ;
self . displayNameTextField . textAlignment = NSTextAlignmentCenter ;
self . displayNameTextField . accessibilityLabel = @ "Edit name text field" ;
self . displayNameTextField . alpha = 0 ;
self . displayNameContainer = [ UIView new ] ;
self . displayNameContainer . accessibilityLabel = @ "Edit name text field" ;
self . displayNameContainer . isAccessibilityElement = YES ;
[ self . displayNameContainer autoSetDimension : ALDimensionHeight toSize : 40 ] ;
[ self . displayNameContainer addSubview : self . displayNameLabel ] ;
[ self . displayNameLabel autoPinToEdgesOfView : self . displayNameContainer ] ;
[ self . displayNameContainer addSubview : self . displayNameTextField ] ;
[ self . displayNameTextField autoPinToEdgesOfView : self . displayNameContainer ] ;
if ( [ self . thread isKindOfClass : TSContactThread . class ] ) {
UITapGestureRecognizer * tapGestureRecognizer = [ [ UITapGestureRecognizer alloc ] initWithTarget : self action : @ selector ( showEditNameUI ) ] ;
[ self . displayNameContainer addGestureRecognizer : tapGestureRecognizer ] ;
}
2018-07-17 20:24:21 +02:00
self . tableView . estimatedRowHeight = 45 ;
self . tableView . rowHeight = UITableViewAutomaticDimension ;
2017-04-17 21:13:15 +02:00
_disappearingMessagesDurationLabel = [ UILabel new ] ;
2019-03-22 20:54:35 +01:00
SET_SUBVIEW _ACCESSIBILITY _IDENTIFIER ( self , _disappearingMessagesDurationLabel ) ;
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 ] ;
2019-10-03 03:30:45 +02:00
2020-08-28 05:48:27 +02:00
NSString * title ;
2019-12-13 01:23:45 +01:00
if ( [ self . thread isKindOfClass : [ TSContactThread class ] ] ) {
2020-08-28 05:48:27 +02:00
title = NSLocalizedString ( @ "Settings" , @ "" ) ;
2019-12-13 01:23:45 +01:00
} else {
2020-08-28 05:48:27 +02:00
title = NSLocalizedString ( @ "Group Settings" , @ "" ) ;
2019-12-13 01:23:45 +01:00
}
2020-08-28 05:48:27 +02:00
[ LKViewControllerUtilities setUpDefaultSessionStyleForVC : self withTitle : title customBackButton : YES ] ;
self . tableView . backgroundColor = UIColor . clearColor ;
2021-03-01 03:43:52 +01:00
2021-03-18 06:25:46 +01:00
if ( [ self . thread isKindOfClass : TSContactThread . class ] ) {
[ self updateNavBarButtons ] ;
}
2017-04-03 16:29:11 +02:00
}
- ( void ) updateTableContents
{
OWSTableContents * contents = [ OWSTableContents new ] ;
contents . title = NSLocalizedString ( @ "CONVERSATION_SETTINGS" , @ "title for conversation settings screen" ) ;
2019-01-04 15:19:41 +01:00
BOOL isNoteToSelf = self . thread . isNoteToSelf ;
2018-12-21 19:03:09 +01:00
2017-08-01 22:16:33 +02:00
__weak OWSConversationSettingsViewController * weakSelf = self ;
2017-04-03 16:29:11 +02:00
2021-07-13 08:09:28 +02:00
OWSTableSection * section = [ OWSTableSection new ] ;
2017-04-10 21:58:34 +02:00
2021-07-13 08:09:28 +02:00
section . customHeaderView = [ self mainSectionHeader ] ;
section . customHeaderHeight = @ ( UITableViewAutomaticDimension ) ;
2017-07-04 22:40:28 +02:00
2021-07-13 08:09:28 +02:00
// Copy Session ID
2020-09-16 02:50:48 +02:00
if ( [ self . thread isKindOfClass : TSContactThread . class ] ) {
2021-07-13 08:09:28 +02:00
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
return [ weakSelf
disclosureCellWithName : NSLocalizedString ( @ "vc_conversation_settings_copy_session_id_button_title" , "" )
iconName : @ "ic_copy"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "copy_session_id" ) ] ;
}
actionBlock : ^ {
[ weakSelf copySessionID ] ;
} ] ] ;
2020-09-16 02:50:48 +02:00
}
2021-07-13 08:09:28 +02:00
// All media
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
return [ weakSelf
disclosureCellWithName : MediaStrings . allMedia
iconName : @ "actionsheet_camera_roll_black"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "all_media" ) ] ;
} actionBlock : ^ {
[ weakSelf showMediaGallery ] ;
} ] ] ;
2021-05-07 05:39:39 +02:00
2021-07-13 08:09:28 +02:00
// Invite button
2021-05-07 05:39:39 +02:00
if ( self . isOpenGroup ) {
2021-07-13 08:09:28 +02:00
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
return [ weakSelf
disclosureCellWithName : NSLocalizedString ( @ "vc_conversation_settings_invite_button_title" , "" )
iconName : @ "ic_plus_24"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "invite" ) ] ;
} actionBlock : ^ {
[ weakSelf inviteUsersToOpenGroup ] ;
} ] ] ;
2021-07-26 07:42:04 +02:00
// Notification Settings
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
UITableViewCell * cell = [ OWSTableItem newCell ] ;
OWSConversationSettingsViewController * strongSelf = weakSelf ;
OWSCAssertDebug ( strongSelf ) ;
cell . preservesSuperviewLayoutMargins = YES ;
cell . contentView . preservesSuperviewLayoutMargins = YES ;
cell . selectionStyle = UITableViewCellSelectionStyleNone ;
UIImageView * iconView = [ strongSelf viewForIconWithName : @ "NotifyMentions" ] ;
UILabel * rowLabel = [ UILabel new ] ;
rowLabel . text = NSLocalizedString (
@ "CONVERSATION_SETTINGS_NOTIFICATION" , @ "" ) ;
rowLabel . textColor = LKColors . text ;
rowLabel . font = [ UIFont systemFontOfSize : LKValues . mediumFontSize ] ;
rowLabel . lineBreakMode = NSLineBreakByTruncatingTail ;
UISwitch * switchView = [ UISwitch new ] ;
switchView . on = ( ( TSGroupThread * ) strongSelf . thread ) . isOnlyNotifyMentions ;
[ switchView addTarget : strongSelf action : @ selector ( notifyMentionsSwitchValueDidChange : )
forControlEvents : UIControlEventValueChanged ] ;
UIStackView * topRow =
[ [ UIStackView alloc ] initWithArrangedSubviews : @ [ iconView , rowLabel , switchView ] ] ;
topRow . spacing = strongSelf . iconSpacing ;
topRow . alignment = UIStackViewAlignmentCenter ;
[ cell . contentView addSubview : topRow ] ;
[ topRow autoPinEdgesToSuperviewMarginsExcludingEdge : ALEdgeBottom ] ;
UILabel * subtitleLabel = [ UILabel new ] ;
subtitleLabel . text = NSLocalizedString ( @ "When enabled, only messages mentioned you will be notified." , @ "" ) ;
subtitleLabel . textColor = LKColors . text ;
subtitleLabel . font = [ UIFont systemFontOfSize : LKValues . smallFontSize ] ;
subtitleLabel . numberOfLines = 0 ;
subtitleLabel . lineBreakMode = NSLineBreakByWordWrapping ;
[ cell . contentView addSubview : subtitleLabel ] ;
[ subtitleLabel autoPinEdge : ALEdgeTop toEdge : ALEdgeBottom ofView : topRow withOffset : 8 ] ;
[ subtitleLabel autoPinEdge : ALEdgeLeading toEdge : ALEdgeLeading ofView : rowLabel ] ;
[ subtitleLabel autoPinTrailingToSuperviewMargin ] ;
[ subtitleLabel autoPinBottomToSuperviewMargin ] ;
cell . userInteractionEnabled = ! strongSelf . hasLeftGroup ;
cell . accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "notify_mentions_only" ) ;
return cell ;
} customRowHeight : UITableViewAutomaticDimension actionBlock : nil ] ] ;
2021-05-07 05:39:39 +02:00
}
2020-09-16 02:08:46 +02:00
2021-07-13 08:09:28 +02:00
// Search
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
NSString * title = NSLocalizedString ( @ "CONVERSATION_SETTINGS_SEARCH" ,
@ "Table cell label in conversation settings which returns the user to the "
@ "conversation with 'search mode' activated" ) ;
return [ weakSelf
disclosureCellWithName : title
iconName : @ "conversation_settings_search"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "search" ) ] ;
} actionBlock : ^ {
[ weakSelf tappedConversationSearch ] ;
} ] ] ;
// Disappearing messages
2020-11-16 00:34:47 +01:00
if ( ! [ self isOpenGroup ] ) {
2021-07-13 08:09:28 +02:00
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
UITableViewCell * cell = [ OWSTableItem newCell ] ;
OWSConversationSettingsViewController * strongSelf = weakSelf ;
OWSCAssertDebug ( strongSelf ) ;
cell . preservesSuperviewLayoutMargins = YES ;
cell . contentView . preservesSuperviewLayoutMargins = YES ;
cell . selectionStyle = UITableViewCellSelectionStyleNone ;
NSString * iconName
= ( strongSelf . disappearingMessagesConfiguration . isEnabled ? @ "ic_timer" : @ "ic_timer_disabled" ) ;
UIImageView * iconView = [ strongSelf viewForIconWithName : iconName ] ;
UILabel * rowLabel = [ UILabel new ] ;
rowLabel . text = NSLocalizedString (
@ "DISAPPEARING_MESSAGES" , @ "table cell label in conversation settings" ) ;
rowLabel . textColor = LKColors . text ;
rowLabel . font = [ UIFont systemFontOfSize : LKValues . mediumFontSize ] ;
rowLabel . lineBreakMode = NSLineBreakByTruncatingTail ;
UISwitch * switchView = [ UISwitch new ] ;
switchView . on = strongSelf . disappearingMessagesConfiguration . isEnabled ;
[ switchView addTarget : strongSelf action : @ selector ( disappearingMessagesSwitchValueDidChange : )
forControlEvents : UIControlEventValueChanged ] ;
UIStackView * topRow =
[ [ UIStackView alloc ] initWithArrangedSubviews : @ [ iconView , rowLabel , switchView ] ] ;
topRow . spacing = strongSelf . iconSpacing ;
topRow . alignment = UIStackViewAlignmentCenter ;
[ cell . contentView addSubview : topRow ] ;
[ topRow autoPinEdgesToSuperviewMarginsExcludingEdge : ALEdgeBottom ] ;
UILabel * subtitleLabel = [ UILabel new ] ;
NSString * displayName ;
if ( self . thread . isGroupThread ) {
displayName = @ "the group" ;
} else {
TSContactThread * thread = ( TSContactThread * ) self . thread ;
displayName = [ [ LKStorage . shared getContactWithSessionID : thread . contactSessionID ] displayNameFor : SNContactContextRegular ] ? : @ "anonymous" ;
}
subtitleLabel . text = [ NSString stringWithFormat : NSLocalizedString ( @ "When enabled, messages between you and %@ will disappear after they have been seen." , "" ) , displayName ] ;
subtitleLabel . textColor = LKColors . text ;
subtitleLabel . font = [ UIFont systemFontOfSize : LKValues . smallFontSize ] ;
subtitleLabel . numberOfLines = 0 ;
subtitleLabel . lineBreakMode = NSLineBreakByWordWrapping ;
[ cell . contentView addSubview : subtitleLabel ] ;
[ subtitleLabel autoPinEdge : ALEdgeTop toEdge : ALEdgeBottom ofView : topRow withOffset : 8 ] ;
[ subtitleLabel autoPinEdge : ALEdgeLeading toEdge : ALEdgeLeading ofView : rowLabel ] ;
[ subtitleLabel autoPinTrailingToSuperviewMargin ] ;
[ subtitleLabel autoPinBottomToSuperviewMargin ] ;
cell . userInteractionEnabled = ! strongSelf . hasLeftGroup ;
cell . accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "disappearing_messages" ) ;
return cell ;
} customRowHeight : UITableViewAutomaticDimension actionBlock : nil ] ] ;
2019-03-22 20:54:35 +01:00
2019-12-13 01:23:45 +01:00
if ( self . disappearingMessagesConfiguration . isEnabled ) {
2021-07-13 08:09:28 +02:00
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
UITableViewCell * cell = [ OWSTableItem newCell ] ;
OWSConversationSettingsViewController * strongSelf = weakSelf ;
OWSCAssertDebug ( strongSelf ) ;
cell . preservesSuperviewLayoutMargins = YES ;
cell . contentView . preservesSuperviewLayoutMargins = YES ;
cell . selectionStyle = UITableViewCellSelectionStyleNone ;
UIImageView * iconView = [ strongSelf viewForIconWithName : @ "ic_timer" ] ;
UILabel * rowLabel = strongSelf . disappearingMessagesDurationLabel ;
[ strongSelf updateDisappearingMessagesDurationLabel ] ;
rowLabel . textColor = LKColors . text ;
rowLabel . font = [ UIFont systemFontOfSize : LKValues . mediumFontSize ] ;
// don ' t truncate useful duration info which is in the tail
rowLabel . lineBreakMode = NSLineBreakByTruncatingHead ;
UIStackView * topRow =
[ [ UIStackView alloc ] initWithArrangedSubviews : @ [ iconView , rowLabel ] ] ;
topRow . spacing = strongSelf . iconSpacing ;
topRow . alignment = UIStackViewAlignmentCenter ;
[ cell . contentView addSubview : topRow ] ;
[ topRow autoPinEdgesToSuperviewMarginsExcludingEdge : ALEdgeBottom ] ;
UISlider * slider = [ UISlider new ] ;
slider . maximumValue = ( float ) ( strongSelf . disappearingMessagesDurations . count - 1 ) ;
slider . minimumValue = 0 ;
slider . tintColor = LKColors . accent ;
slider . continuous = NO ;
slider . value = strongSelf . disappearingMessagesConfiguration . durationIndex ;
[ slider addTarget : strongSelf action : @ selector ( durationSliderDidChange : )
forControlEvents : UIControlEventValueChanged ] ;
[ cell . contentView addSubview : slider ] ;
[ slider autoPinEdge : ALEdgeTop toEdge : ALEdgeBottom ofView : topRow withOffset : 6 ] ;
[ slider autoPinEdge : ALEdgeLeading toEdge : ALEdgeLeading ofView : rowLabel ] ;
[ slider autoPinTrailingToSuperviewMargin ] ;
[ slider autoPinBottomToSuperviewMargin ] ;
cell . userInteractionEnabled = ! strongSelf . hasLeftGroup ;
cell . accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER _WITH _NAME (
OWSConversationSettingsViewController , @ "disappearing_messages_duration" ) ;
return cell ;
} customRowHeight : UITableViewAutomaticDimension actionBlock : nil ] ] ;
2019-12-13 01:23:45 +01:00
}
2017-04-03 16:29:11 +02:00
}
2021-07-13 08:09:28 +02:00
[ contents addSection : section ] ;
2017-04-03 16:29:11 +02:00
2021-07-13 08:09:28 +02:00
// Closed group settings
2020-09-30 02:13:49 +02:00
__block BOOL isUserMember = NO ;
if ( self . isGroupThread ) {
2021-01-11 04:37:49 +01:00
NSString * userPublicKey = [ SNGeneralUtilities getUserPublicKey ] ;
2020-11-16 00:34:47 +01:00
isUserMember = [ ( TSGroupThread * ) self . thread isUserMemberInGroup : userPublicKey ] ;
2020-09-30 02:13:49 +02:00
}
2020-11-16 00:34:47 +01:00
if ( self . isGroupThread && self . isClosedGroup && isUserMember ) {
2021-07-13 08:09:28 +02:00
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
UITableViewCell * cell =
[ weakSelf disclosureCellWithName : NSLocalizedString ( @ "EDIT_GROUP_ACTION" , @ "table cell label in conversation settings" )
iconName : @ "table_ic_group_edit"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "edit_group" ) ] ;
cell . userInteractionEnabled = ! weakSelf . hasLeftGroup ;
return cell ;
} actionBlock : ^ {
[ weakSelf editGroup ] ;
} ] ] ;
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
UITableViewCell * cell =
[ weakSelf disclosureCellWithName : NSLocalizedString ( @ "LEAVE_GROUP_ACTION" , @ "table cell label in conversation settings" )
iconName : @ "table_ic_group_leave"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "leave_group" ) ] ;
cell . userInteractionEnabled = ! weakSelf . hasLeftGroup ;
return cell ;
} actionBlock : ^ {
[ weakSelf didTapLeaveGroup ] ;
} ] ] ;
}
if ( ! isNoteToSelf ) {
// Notification sound
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
UITableViewCell * cell =
[ [ UITableViewCell alloc ] initWithStyle : UITableViewCellStyleValue1 reuseIdentifier : nil ] ;
[ OWSTableItem configureCell : cell ] ;
OWSConversationSettingsViewController * strongSelf = weakSelf ;
OWSCAssertDebug ( strongSelf ) ;
cell . preservesSuperviewLayoutMargins = YES ;
cell . contentView . preservesSuperviewLayoutMargins = YES ;
UIImageView * iconView = [ strongSelf viewForIconWithName : @ "table_ic_notification_sound" ] ;
UILabel * rowLabel = [ UILabel new ] ;
rowLabel . text = NSLocalizedString ( @ "SETTINGS_ITEM_NOTIFICATION_SOUND" ,
@ "Label for settings view that allows user to change the notification sound." ) ;
rowLabel . textColor = LKColors . text ;
rowLabel . font = [ UIFont systemFontOfSize : LKValues . mediumFontSize ] ;
rowLabel . lineBreakMode = NSLineBreakByTruncatingTail ;
UIStackView * contentRow =
[ [ UIStackView alloc ] initWithArrangedSubviews : @ [ iconView , rowLabel ] ] ;
contentRow . spacing = strongSelf . iconSpacing ;
contentRow . alignment = UIStackViewAlignmentCenter ;
[ cell . contentView addSubview : contentRow ] ;
[ contentRow autoPinEdgesToSuperviewMargins ] ;
OWSSound sound = [ OWSSounds notificationSoundForThread : strongSelf . thread ] ;
cell . detailTextLabel . text = [ OWSSounds displayNameForSound : sound ] ;
cell . accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER _WITH _NAME (
OWSConversationSettingsViewController , @ "notifications" ) ;
return cell ;
2020-09-25 08:20:42 +02:00
}
2021-07-13 08:09:28 +02:00
customRowHeight : UITableViewAutomaticDimension
actionBlock : ^ {
OWSSoundSettingsViewController * vc = [ OWSSoundSettingsViewController new ] ;
vc . thread = weakSelf . thread ;
[ weakSelf . navigationController pushViewController : vc animated : YES ] ;
} ] ] ;
// Mute thread
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
OWSConversationSettingsViewController * strongSelf = weakSelf ;
if ( ! strongSelf ) { return [ UITableViewCell new ] ; }
NSString * cellTitle = NSLocalizedString ( @ "CONVERSATION_SETTINGS_MUTE_LABEL" , @ "label for 'mute thread' cell in conversation settings" ) ;
UITableViewCell * cell = [ strongSelf disclosureCellWithName : cellTitle iconName : @ "Mute"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "mute" ) ] ;
cell . selectionStyle = UITableViewCellSelectionStyleNone ;
UISwitch * muteConversationSwitch = [ UISwitch new ] ;
NSDate * mutedUntilDate = strongSelf . thread . mutedUntilDate ;
NSDate * now = [ NSDate date ] ;
muteConversationSwitch . on = ( mutedUntilDate ! = nil && [ mutedUntilDate timeIntervalSinceDate : now ] > 0 ) ;
[ muteConversationSwitch addTarget : strongSelf action : @ selector ( handleMuteSwitchToggled : )
forControlEvents : UIControlEventValueChanged ] ;
cell . accessoryView = muteConversationSwitch ;
return cell ;
} actionBlock : nil ] ] ;
2017-04-03 16:29:11 +02:00
}
2020-01-13 01:14:49 +01:00
2021-07-13 08:09:28 +02:00
// Block contact
if ( ! isNoteToSelf && [ self . thread isKindOfClass : TSContactThread . class ] ) {
[ section addItem : [ OWSTableItem itemWithCustomCellBlock : ^ {
OWSConversationSettingsViewController * strongSelf = weakSelf ;
if ( ! strongSelf ) { return [ UITableViewCell new ] ; }
2017-04-03 16:29:11 +02:00
2021-07-13 08:09:28 +02:00
NSString * cellTitle = NSLocalizedString ( @ "CONVERSATION_SETTINGS_BLOCK_THIS_USER" , @ "table cell label in conversation settings" ) ;
UITableViewCell * cell = [ strongSelf disclosureCellWithName : cellTitle iconName : @ "table_ic_block"
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( OWSConversationSettingsViewController , @ "block" ) ] ;
2017-04-17 21:13:15 +02:00
2021-07-13 08:09:28 +02:00
cell . selectionStyle = UITableViewCellSelectionStyleNone ;
2017-04-17 21:13:15 +02:00
2021-07-13 08:09:28 +02:00
UISwitch * blockConversationSwitch = [ UISwitch new ] ;
blockConversationSwitch . on = [ strongSelf . blockingManager isThreadBlocked : strongSelf . thread ] ;
[ blockConversationSwitch addTarget : strongSelf action : @ selector ( blockConversationSwitchDidChange : )
forControlEvents : UIControlEventValueChanged ] ;
cell . accessoryView = blockConversationSwitch ;
return cell ;
} actionBlock : nil ] ] ;
2018-12-21 19:03:09 +01:00
}
2018-09-07 23:45:54 +02:00
2017-04-03 16:29:11 +02:00
self . contents = contents ;
2016-09-21 14:37:51 +02:00
}
2017-07-11 18:17:28 +02:00
- ( CGFloat ) iconSpacing
{
return 12. f ;
}
2017-08-01 22:16:33 +02:00
- ( UITableViewCell * ) cellWithName : ( NSString * ) name iconName : ( NSString * ) iconName
2017-06-05 23:33:29 +02:00
{
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( iconName . length > 0 ) ;
2018-07-03 18:57:51 +02:00
UIImageView * iconView = [ self viewForIconWithName : iconName ] ;
return [ self cellWithName : name iconView : iconView ] ;
}
- ( UITableViewCell * ) cellWithName : ( NSString * ) name iconView : ( UIView * ) iconView
{
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( name . length > 0 ) ;
2017-06-05 23:33:29 +02:00
2018-07-13 00:14:04 +02:00
UITableViewCell * cell = [ OWSTableItem newCell ] ;
2017-07-11 18:17:28 +02:00
cell . preservesSuperviewLayoutMargins = YES ;
cell . contentView . preservesSuperviewLayoutMargins = YES ;
2017-06-05 23:33:29 +02:00
UILabel * rowLabel = [ UILabel new ] ;
rowLabel . text = name ;
2019-12-13 01:23:45 +01:00
rowLabel . textColor = LKColors . text ;
rowLabel . font = [ UIFont systemFontOfSize : LKValues . mediumFontSize ] ;
2017-06-05 23:33:29 +02:00
rowLabel . lineBreakMode = NSLineBreakByTruncatingTail ;
2018-07-17 20:24:21 +02:00
UIStackView * contentRow = [ [ UIStackView alloc ] initWithArrangedSubviews : @ [ iconView , rowLabel ] ] ;
contentRow . spacing = self . iconSpacing ;
[ cell . contentView addSubview : contentRow ] ;
[ contentRow autoPinEdgesToSuperviewMargins ] ;
2017-06-05 23:33:29 +02:00
return cell ;
}
2019-03-22 20:54:35 +01:00
- ( UITableViewCell * ) disclosureCellWithName : ( NSString * ) name
iconName : ( NSString * ) iconName
accessibilityIdentifier : ( NSString * ) accessibilityIdentifier
2017-08-01 22:16:33 +02:00
{
UITableViewCell * cell = [ self cellWithName : name iconName : iconName ] ;
2019-03-22 20:54:35 +01:00
cell . accessibilityIdentifier = accessibilityIdentifier ;
2017-08-01 22:16:33 +02:00
return cell ;
}
2019-03-22 20:54:35 +01:00
- ( UITableViewCell * ) labelCellWithName : ( NSString * ) name
iconName : ( NSString * ) iconName
accessibilityIdentifier : ( NSString * ) accessibilityIdentifier
2017-08-01 22:16:33 +02:00
{
UITableViewCell * cell = [ self cellWithName : name iconName : iconName ] ;
cell . accessoryType = UITableViewCellAccessoryNone ;
2019-03-22 20:54:35 +01:00
cell . accessibilityIdentifier = accessibilityIdentifier ;
2017-08-01 22:16:33 +02:00
return cell ;
}
2021-02-18 06:49:48 +01:00
- ( void ) showProfilePicture : ( UITapGestureRecognizer * ) tapGesture
2020-10-29 06:13:16 +01:00
{
2020-10-30 00:04:30 +01:00
LKProfilePictureView * profilePictureView = ( LKProfilePictureView * ) tapGesture . view ;
UIImage * image = [ profilePictureView getProfilePicture ] ;
2020-10-29 06:13:16 +01:00
if ( image = = nil ) { return ; }
2021-02-18 06:49:48 +01:00
NSString * title = ( self . threadName ! = nil && self . threadName . length > 0 ) ? self . threadName : @ "Anonymous" ;
SNProfilePictureVC * profilePictureVC = [ [ SNProfilePictureVC alloc ] initWithImage : image title : title ] ;
UINavigationController * navController = [ [ UINavigationController alloc ] initWithRootViewController : profilePictureVC ] ;
navController . modalPresentationStyle = UIModalPresentationFullScreen ;
[ self presentViewController : navController animated : YES completion : nil ] ;
2020-10-29 06:13:16 +01:00
}
2017-07-04 22:40:28 +02:00
- ( UIView * ) mainSectionHeader
2017-04-17 21:13:15 +02:00
{
2020-10-29 06:13:16 +01:00
UITapGestureRecognizer * profilePictureTapGestureRecognizer = [ [ UITapGestureRecognizer alloc ] initWithTarget : self action : @ selector ( showProfilePicture : ) ] ;
2019-12-13 01:23:45 +01:00
LKProfilePictureView * profilePictureView = [ LKProfilePictureView new ] ;
CGFloat size = LKValues . largeProfilePictureSize ;
profilePictureView . size = size ;
[ profilePictureView autoSetDimension : ALDimensionWidth toSize : size ] ;
[ profilePictureView autoSetDimension : ALDimensionHeight toSize : size ] ;
2020-10-29 06:13:16 +01:00
[ profilePictureView addGestureRecognizer : profilePictureTapGestureRecognizer ] ;
2019-12-13 01:23:45 +01:00
2021-03-01 03:15:54 +01:00
self . displayNameLabel . text = ( self . threadName ! = nil && self . threadName . length > 0 ) ? self . threadName : @ "Anonymous" ;
if ( [ self . thread isKindOfClass : TSContactThread . class ] ) {
UITapGestureRecognizer * tapGestureRecognizer = [ [ UITapGestureRecognizer alloc ] initWithTarget : self action : @ selector ( showEditNameUI ) ] ;
[ self . displayNameContainer addGestureRecognizer : tapGestureRecognizer ] ;
}
2019-12-13 01:23:45 +01:00
2021-03-01 03:15:54 +01:00
UIStackView * stackView = [ [ UIStackView alloc ] initWithArrangedSubviews : @ [ profilePictureView , self . displayNameContainer ] ] ;
2019-12-13 01:23:45 +01:00
stackView . axis = UILayoutConstraintAxisVertical ;
stackView . spacing = LKValues . mediumSpacing ;
stackView . distribution = UIStackViewDistributionEqualCentering ;
stackView . alignment = UIStackViewAlignmentCenter ;
2020-05-29 07:11:08 +02:00
BOOL isSmallScreen = ( UIScreen . mainScreen . bounds . size . height - 568 ) < 1 ;
CGFloat horizontalSpacing = isSmallScreen ? LKValues . largeSpacing : LKValues . veryLargeSpacing ;
stackView . layoutMargins = UIEdgeInsetsMake ( LKValues . mediumSpacing , horizontalSpacing , LKValues . mediumSpacing , horizontalSpacing ) ;
2019-12-13 01:23:45 +01:00
[ stackView setLayoutMarginsRelativeArrangement : YES ] ;
2020-09-14 03:31:45 +02:00
if ( ! self . isGroupThread ) {
2020-05-29 07:11:08 +02:00
SRCopyableLabel * subtitleView = [ SRCopyableLabel new ] ;
2019-12-13 01:23:45 +01:00
subtitleView . textColor = LKColors . text ;
2020-05-29 07:11:08 +02:00
subtitleView . font = [ LKFonts spaceMonoOfSize : LKValues . smallFontSize ] ;
2019-12-13 01:23:45 +01:00
subtitleView . lineBreakMode = NSLineBreakByCharWrapping ;
subtitleView . numberOfLines = 2 ;
2021-05-05 02:00:39 +02:00
subtitleView . text = ( ( TSContactThread * ) self . thread ) . contactSessionID ;
2019-12-13 01:23:45 +01:00
subtitleView . textAlignment = NSTextAlignmentCenter ;
[ stackView addArrangedSubview : subtitleView ] ;
2019-09-10 08:26:45 +02:00
}
2019-12-13 01:23:45 +01:00
2020-09-14 03:31:45 +02:00
[ profilePictureView updateForThread : self . thread ] ;
2019-12-13 01:23:45 +01:00
return stackView ;
2017-04-17 21:13:15 +02:00
}
- ( UIImageView * ) viewForIconWithName : ( NSString * ) iconName
{
UIImage * icon = [ UIImage imageNamed : iconName ] ;
2018-01-20 17:27:32 +01:00
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( icon ) ;
2017-04-17 21:13:15 +02:00
UIImageView * iconView = [ UIImageView new ] ;
iconView . image = [ icon imageWithRenderingMode : UIImageRenderingModeAlwaysTemplate ] ;
2020-03-17 06:18:53 +01:00
iconView . tintColor = LKColors . text ;
2018-01-20 17:27:32 +01:00
iconView . contentMode = UIViewContentModeScaleAspectFit ;
iconView . layer . minificationFilter = kCAFilterTrilinear ;
iconView . layer . magnificationFilter = kCAFilterTrilinear ;
2018-07-03 18:57:51 +02:00
[ iconView autoSetDimensionsToSize : CGSizeMake ( kIconViewLength , kIconViewLength ) ] ;
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
2018-07-19 00:48:02 +02:00
NSIndexPath * _Nullable selectedPath = [ self . tableView indexPathForSelectedRow ] ;
if ( selectedPath ) {
// HACK to unselect rows when swiping back
// http : // stackoverflow . com / questions / 19379510 / uitableviewcell - doesnt - get - deselected - when - swiping - back - quickly
[ self . tableView deselectRowAtIndexPath : selectedPath animated : animated ] ;
}
2017-07-04 22:40:28 +02:00
[ self updateTableContents ] ;
2016-09-21 14:37:51 +02:00
}
- ( 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 ) {
2020-11-26 05:51:12 +01:00
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * _Nonnull transaction ) {
2018-10-20 19:51:48 +02:00
[ self . disappearingMessagesConfiguration saveWithTransaction : transaction ] ;
2020-11-26 03:30:30 +01:00
OWSDisappearingConfigurationUpdateInfoMessage * infoMessage = [ [ OWSDisappearingConfigurationUpdateInfoMessage alloc ]
2018-10-20 19:51:48 +02:00
initWithTimestamp : [ NSDate ows_millisecondTimeStamp ]
thread : self . thread
configuration : self . disappearingMessagesConfiguration
createdByRemoteName : nil
createdInExistingGroup : NO ] ;
[ infoMessage saveWithTransaction : transaction ] ;
2020-11-26 03:30:30 +01:00
SNExpirationTimerUpdate * expirationTimerUpdate = [ SNExpirationTimerUpdate new ] ;
2020-11-27 01:08:48 +01:00
BOOL isEnabled = self . disappearingMessagesConfiguration . enabled ;
expirationTimerUpdate . duration = isEnabled ? self . disappearingMessagesConfiguration . durationSeconds : 0 ;
2020-11-26 04:01:24 +01:00
[ SNMessageSender send : expirationTimerUpdate inThread : self . thread usingTransaction : transaction ] ;
2020-11-04 01:46:30 +01:00
} ] ;
2016-09-21 14:37:51 +02:00
}
}
# pragma mark - Actions
2020-09-25 08:20:42 +02:00
- ( void ) editGroup
{
2021-03-04 23:18:45 +01:00
SNEditClosedGroupVC * editClosedGroupVC = [ [ SNEditClosedGroupVC alloc ] initWithThreadID : self . thread . uniqueId ] ;
2020-09-28 03:43:15 +02:00
[ self . navigationController pushViewController : editClosedGroupVC animated : YES completion : nil ] ;
2020-09-25 08:20:42 +02:00
}
2016-09-21 14:37:51 +02:00
- ( void ) didTapLeaveGroup
{
2021-01-11 04:37:49 +01:00
NSString * userPublicKey = [ SNGeneralUtilities getUserPublicKey ] ;
2021-01-10 23:55:20 +01:00
NSString * message ;
if ( [ ( ( TSGroupThread * ) self . thread ) . groupModel . groupAdminIds containsObject : userPublicKey ] ) {
message = @ "Because you are the creator of this group it will be deleted for everyone. This cannot be undone." ;
} else {
message = NSLocalizedString ( @ "CONFIRM_LEAVE_GROUP_DESCRIPTION" , @ "Alert body" ) ;
}
2019-03-21 15:55:04 +01:00
UIAlertController * alert =
2016-09-21 14:37:51 +02:00
[ UIAlertController alertControllerWithTitle : NSLocalizedString ( @ "CONFIRM_LEAVE_GROUP_TITLE" , @ "Alert title" )
2021-01-10 23:55:20 +01:00
message : message
2016-09-21 14:37:51 +02:00
preferredStyle : UIAlertControllerStyleAlert ] ;
UIAlertAction * leaveAction = [ UIAlertAction
2019-03-22 20:54:35 +01:00
actionWithTitle : NSLocalizedString ( @ "LEAVE_BUTTON_TITLE" , @ "Confirmation button within contextual alert" )
accessibilityIdentifier : ACCESSIBILITY_IDENTIFIER _WITH _NAME ( self , @ "leave_group_confirm" )
style : UIAlertActionStyleDestructive
handler : ^ ( UIAlertAction * _Nonnull action ) {
[ self leaveGroup ] ;
} ] ;
2019-03-21 15:55:04 +01:00
[ alert addAction : leaveAction ] ;
[ alert addAction : [ OWSAlerts cancelAction ] ] ;
2016-09-21 14:37:51 +02:00
2019-03-21 15:55:04 +01:00
[ self presentAlert : alert ] ;
2016-09-21 14:37:51 +02:00
}
2018-09-11 01:48:37 +02:00
- ( BOOL ) hasLeftGroup
{
if ( self . isGroupThread ) {
TSGroupThread * groupThread = ( TSGroupThread * ) self . thread ;
2020-11-17 06:23:13 +01:00
return ! groupThread . isCurrentUserMemberInGroup ;
2018-09-11 01:48:37 +02:00
}
return NO ;
}
2016-09-21 14:37:51 +02:00
- ( void ) leaveGroup
{
TSGroupThread * gThread = ( TSGroupThread * ) self . thread ;
2018-09-10 19:25:38 +02:00
2021-01-11 04:12:07 +01:00
if ( gThread . isClosedGroup ) {
2020-09-25 05:41:35 +02:00
NSString * groupPublicKey = [ LKGroupUtilities getDecodedGroupID : gThread . groupModel . groupId ] ;
[ LKStorage writeSyncWithBlock : ^ ( YapDatabaseReadWriteTransaction * _Nonnull transaction ) {
2021-04-15 05:15:15 +02:00
[ [ SNMessageSender leaveClosedGroupWithPublicKey : groupPublicKey using : transaction ] retainUntilComplete ] ;
2020-11-04 01:46:30 +01:00
} ] ;
2020-09-25 05:41:35 +02:00
}
2016-09-21 14:37:51 +02:00
[ self . navigationController popViewControllerAnimated : 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
}
2021-07-13 08:09:28 +02:00
- ( void ) handleMuteSwitchToggled : ( id ) sender
{
UISwitch * uiSwitch = ( UISwitch * ) sender ;
if ( uiSwitch . isOn ) {
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
[ self . thread updateWithMutedUntilDate : [ NSDate distantFuture ] transaction : transaction ] ;
} ] ;
} else {
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
[ self . thread updateWithMutedUntilDate : nil transaction : transaction ] ;
} ] ;
}
if ( self . isClosedGroup ) {
NSString * groupPublicKey = [ LKGroupUtilities getDecodedGroupID : ( ( TSGroupThread * ) self . thread ) . groupModel . groupId ] ;
NSString * userPublicKey = [ SNGeneralUtilities getUserPublicKey ] ;
if ( uiSwitch . isOn ) {
[ [ LKPushNotificationAPI performOperation : ClosedGroupOperationUnsubscribe
forClosedGroupWithPublicKey : groupPublicKey userPublicKey : userPublicKey ] retainUntilComplete ] ;
} else {
[ [ LKPushNotificationAPI performOperation : ClosedGroupOperationSubscribe
forClosedGroupWithPublicKey : groupPublicKey userPublicKey : userPublicKey ] retainUntilComplete ] ;
}
}
}
2018-09-07 23:45:54 +02:00
- ( void ) blockConversationSwitchDidChange : ( id ) sender
2016-09-21 14:37:51 +02:00
{
2017-04-03 16:29:11 +02:00
if ( ! [ sender isKindOfClass : [ UISwitch class ] ] ) {
2018-08-27 18:51:32 +02:00
OWSFailDebug ( @ "Unexpected sender for block user switch: %@" , sender ) ;
2017-04-03 16:29:11 +02:00
}
2018-09-07 23:45:54 +02:00
UISwitch * blockConversationSwitch = ( UISwitch * ) sender ;
2017-04-03 16:29:11 +02:00
2018-09-07 23:45:54 +02:00
BOOL isCurrentlyBlocked = [ self . blockingManager isThreadBlocked : self . thread ] ;
2016-09-21 14:37:51 +02:00
2019-02-25 18:58:15 +01:00
__weak OWSConversationSettingsViewController * weakSelf = self ;
2018-09-07 23:45:54 +02:00
if ( blockConversationSwitch . isOn ) {
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( ! isCurrentlyBlocked ) ;
2017-04-03 16:29:11 +02:00
if ( isCurrentlyBlocked ) {
return ;
}
2018-09-07 23:45:54 +02:00
[ BlockListUIUtils showBlockThreadActionSheet : self . thread
fromViewController : self
2018-09-10 19:25:38 +02:00
blockingManager : self . blockingManager
2018-09-07 23:45:54 +02:00
completionBlock : ^ ( BOOL isBlocked ) {
// Update switch state if user cancels action .
blockConversationSwitch . on = isBlocked ;
2019-02-25 18:58:15 +01:00
[ weakSelf updateTableContents ] ;
2018-09-07 23:45:54 +02:00
} ] ;
2018-09-10 19:25:38 +02:00
2016-09-21 14:37:51 +02:00
} else {
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( isCurrentlyBlocked ) ;
2017-04-03 16:29:11 +02:00
if ( ! isCurrentlyBlocked ) {
return ;
}
2018-09-07 23:45:54 +02:00
[ BlockListUIUtils showUnblockThreadActionSheet : self . thread
fromViewController : self
2018-12-21 19:03:09 +01:00
blockingManager : self . blockingManager
2018-09-07 23:45:54 +02:00
completionBlock : ^ ( BOOL isBlocked ) {
// Update switch state if user cancels action .
blockConversationSwitch . on = isBlocked ;
2019-02-25 18:58:15 +01:00
[ weakSelf updateTableContents ] ;
2018-09-07 23:45:54 +02:00
} ] ;
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-07-25 19:56:16 +02:00
[ self updateTableContents ] ;
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 ) {
2020-03-17 06:18:53 +01:00
NSString * keepForFormat = @ "Disappear after %@" ;
2016-09-21 14:37:51 +02:00
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 ] ;
}
2020-09-16 02:50:48 +02:00
- ( void ) copySessionID
{
2021-05-05 02:00:39 +02:00
UIPasteboard . generalPasteboard . string = ( ( TSContactThread * ) self . thread ) . contactSessionID ;
2016-09-21 14:37:51 +02:00
}
2021-05-07 05:39:39 +02:00
- ( void ) inviteUsersToOpenGroup
{
2021-05-07 06:08:52 +02:00
NSString * threadID = self . thread . uniqueId ;
SNOpenGroupV2 * openGroup = [ LKStorage . shared getV2OpenGroupForThreadID : threadID ] ;
NSString * url = [ NSString stringWithFormat : @ "%@/%@?public_key=%@" , openGroup . server , openGroup . room , openGroup . publicKey ] ;
SNUserSelectionVC * userSelectionVC = [ [ SNUserSelectionVC alloc ] initWithTitle : NSLocalizedString ( @ "vc_conversation_settings_invite_button_title" , @ "" )
2021-05-07 05:50:32 +02:00
excluding : [ NSSet new ]
completion : ^ ( NSSet < NSString * > * selectedUsers ) {
2021-05-07 06:08:52 +02:00
for ( NSString * user in selectedUsers ) {
SNVisibleMessage * message = [ SNVisibleMessage new ] ;
message . sentTimestamp = [ NSDate millisecondTimestamp ] ;
message . openGroupInvitation = [ [ SNOpenGroupInvitation alloc ] initWithName : openGroup . name url : url ] ;
2021-05-07 07:06:20 +02:00
TSContactThread * thread = [ TSContactThread getOrCreateThreadWithContactSessionID : user ] ;
TSOutgoingMessage * tsMessage = [ TSOutgoingMessage from : message associatedWith : thread ] ;
2021-05-07 06:08:52 +02:00
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
[ tsMessage saveWithTransaction : transaction ] ;
} ] ;
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
[ SNMessageSender send : message inThread : thread usingTransaction : transaction ] ;
} ] ;
}
2021-05-07 05:50:32 +02:00
} ] ;
[ self . navigationController pushViewController : userSelectionVC animated : YES ] ;
2021-05-07 05:39:39 +02:00
}
2018-03-15 18:46:29 +01:00
- ( void ) showMediaGallery
{
2018-11-01 01:12:56 +01:00
OWSLogDebug ( @ "" ) ;
2018-03-15 18:46:29 +01:00
2018-11-01 01:12:56 +01:00
MediaGallery * mediaGallery = [ [ MediaGallery alloc ] initWithThread : self . thread
options : MediaGalleryOptionSliderEnabled ] ;
2018-03-19 17:22:39 +01:00
2018-11-15 01:53:58 +01:00
self . mediaGallery = mediaGallery ;
2018-03-19 20:20:33 +01:00
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( [ self . navigationController isKindOfClass : [ OWSNavigationController class ] ] ) ;
2018-11-01 01:12:56 +01:00
[ mediaGallery pushTileViewFromNavController : ( OWSNavigationController * ) self . navigationController ] ;
2018-03-15 18:46:29 +01:00
}
2018-11-15 01:53:58 +01:00
2019-02-11 17:49:26 +01:00
- ( void ) tappedConversationSearch
{
[ self . conversationSettingsViewDelegate conversationSettingsDidRequestConversationSearch : self ] ;
}
2021-07-26 07:42:04 +02:00
- ( void ) notifyMentionsSwitchValueDidChange : ( id ) sender
{
UISwitch * uiSwitch = ( UISwitch * ) sender ;
if ( uiSwitch . isOn ) {
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
2021-07-26 08:16:14 +02:00
[ ( TSGroupThread * ) self . thread setIsOnlyNotifyMentions : true withTransaction : transaction ] ;
2021-07-26 07:42:04 +02:00
} ] ;
} else {
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
2021-07-26 08:16:14 +02:00
[ ( TSGroupThread * ) self . thread setIsOnlyNotifyMentions : false withTransaction : transaction ] ;
2021-07-26 07:42:04 +02:00
} ] ;
}
}
2021-03-01 03:15:54 +01:00
- ( void ) hideEditNameUI
{
self . isEditingDisplayName = NO ;
}
- ( void ) showEditNameUI
{
self . isEditingDisplayName = YES ;
}
- ( void ) setIsEditingDisplayName : ( BOOL ) isEditingDisplayName
{
_isEditingDisplayName = isEditingDisplayName ;
[ self updateNavBarButtons ] ;
[ UIView animateWithDuration : 0.25 animations : ^ {
self . displayNameLabel . alpha = self . isEditingDisplayName ? 0 : 1 ;
self . displayNameTextField . alpha = self . isEditingDisplayName ? 1 : 0 ;
} ] ;
if ( self . isEditingDisplayName ) {
[ self . displayNameTextField becomeFirstResponder ] ;
} else {
[ self . displayNameTextField resignFirstResponder ] ;
}
}
- ( void ) saveName
{
if ( ! [ self . thread isKindOfClass : TSContactThread . class ] ) { return ; }
2021-05-05 02:00:39 +02:00
SNContact * contact = [ LKStorage . shared getContactWithSessionID : ( ( TSContactThread * ) self . thread ) . contactSessionID ] ;
2021-03-01 03:15:54 +01:00
if ( contact = = nil ) { return ; }
NSString * text = [ self . displayNameTextField . text stringByTrimmingCharactersInSet : NSCharacterSet . whitespaceAndNewlineCharacterSet ] ;
contact . nickname = text . length > 0 ? text : nil ;
[ LKStorage writeWithBlock : ^ ( YapDatabaseReadWriteTransaction * transaction ) {
[ LKStorage . shared setContact : contact usingTransaction : transaction ] ;
} ] ;
self . displayNameLabel . text = text . length > 0 ? text : contact . name ;
[ self hideEditNameUI ] ;
}
- ( void ) updateNavBarButtons
{
if ( self . isEditingDisplayName ) {
UIBarButtonItem * cancelButton = [ [ UIBarButtonItem alloc ] initWithBarButtonSystemItem : UIBarButtonSystemItemCancel target : self action : @ selector ( hideEditNameUI ) ] ;
cancelButton . tintColor = LKColors . text ;
cancelButton . accessibilityLabel = @ "Cancel button" ;
cancelButton . isAccessibilityElement = YES ;
self . navigationItem . leftBarButtonItem = cancelButton ;
UIBarButtonItem * doneButton = [ [ UIBarButtonItem alloc ] initWithBarButtonSystemItem : UIBarButtonSystemItemDone target : self action : @ selector ( saveName ) ] ;
doneButton . tintColor = LKColors . text ;
doneButton . accessibilityLabel = @ "Done button" ;
doneButton . isAccessibilityElement = YES ;
self . navigationItem . rightBarButtonItem = doneButton ;
} else {
self . navigationItem . leftBarButtonItem = nil ;
UIBarButtonItem * editButton = [ [ UIBarButtonItem alloc ] initWithBarButtonSystemItem : UIBarButtonSystemItemEdit target : self action : @ selector ( showEditNameUI ) ] ;
editButton . tintColor = LKColors . text ;
editButton . accessibilityLabel = @ "Done button" ;
editButton . isAccessibilityElement = YES ;
self . navigationItem . rightBarButtonItem = editButton ;
}
}
2017-06-09 22:21:59 +02:00
# pragma mark - Notifications
- ( void ) identityStateDidChange : ( NSNotification * ) notification
{
2017-12-19 17:38:25 +01:00
OWSAssertIsOnMainThread ( ) ;
2017-06-09 22:21:59 +02:00
[ self updateTableContents ] ;
}
2017-08-23 23:09:43 +02:00
- ( void ) otherUsersProfileDidChange : ( NSNotification * ) notification
{
2017-12-19 17:38:25 +01:00
OWSAssertIsOnMainThread ( ) ;
2017-08-23 23:09:43 +02:00
NSString * recipientId = notification . userInfo [ kNSNotificationKey_ProfileRecipientId ] ;
2018-09-06 19:01:24 +02:00
OWSAssertDebug ( recipientId . length > 0 ) ;
2017-08-23 23:09:43 +02:00
if ( recipientId . length > 0 && [ self . thread isKindOfClass : [ TSContactThread class ] ] &&
2021-05-05 02:00:39 +02:00
[ ( ( TSContactThread * ) self . thread ) . contactSessionID isEqualToString : recipientId ] ) {
2017-08-23 23:09:43 +02:00
[ self updateTableContents ] ;
}
}
2018-09-27 03:10:28 +02:00
# pragma mark - OWSSheetViewController
- ( void ) sheetViewControllerRequestedDismiss : ( OWSSheetViewController * ) sheetViewController
2018-06-28 19:28:14 +02:00
{
[ self dismissViewControllerAnimated : YES completion : nil ] ;
}
2016-09-21 14:37:51 +02:00
@ end
NS_ASSUME _NONNULL _END