From 72082edad8dad33083ecd555f7e70fa80a200226 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 25 Feb 2019 12:58:15 -0500 Subject: [PATCH] Fix a visual bug that would sometimes occur while rendering settings switches. Thanks to Gunnar C. Pope for the bug report. --- .../AdvancedSettingsTableViewController.m | 31 +++++---- .../AppSettings/BlockListViewController.m | 38 ++++++----- .../NotificationSettingsViewController.m | 6 +- .../OWSBackupSettingsViewController.m | 8 ++- .../PrivacySettingsTableViewController.m | 68 +++++++++++++------ .../OWSConversationSettingsViewController.m | 5 ++ .../ViewControllers/OWSTableViewController.h | 12 ++-- .../ViewControllers/OWSTableViewController.m | 21 ++++-- 8 files changed, 124 insertions(+), 65 deletions(-) diff --git a/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m b/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m index 294ba1beb..fb4c72b6a 100644 --- a/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AdvancedSettingsTableViewController.m @@ -89,7 +89,9 @@ NS_ASSUME_NONNULL_BEGIN OWSTableSection *loggingSection = [OWSTableSection new]; loggingSection.headerTitle = NSLocalizedString(@"LOGGING_SECTION", nil); [loggingSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_ADVANCED_DEBUGLOG", @"") - isOn:[OWSPreferences isLoggingEnabled] + isOnBlock:^{ + return [OWSPreferences isLoggingEnabled]; + } target:weakSelf selector:@selector(didToggleEnableLogSwitch:)]]; @@ -160,21 +162,26 @@ NS_ASSUME_NONNULL_BEGIN // * ...The internet is not reachable, since we don't want to let users to activate // censorship circumvention unnecessarily, e.g. if they just don't have a valid // internet connection. - BOOL isManualCensorshipCircumventionOnEnabled - = (OWSSignalService.sharedInstance.isCensorshipCircumventionManuallyActivated + OWSTableSwitchBlock isCensorshipCircumventionOnBlock = ^{ + if (OWSSignalService.sharedInstance.hasCensoredPhoneNumber) { + return YES; + } else { + return OWSSignalService.sharedInstance.isCensorshipCircumventionManuallyActivated; + } + }; + Reachability *reachability = self.reachability; + OWSTableSwitchBlock isManualCensorshipCircumventionOnEnabledBlock = ^{ + BOOL isAnySocketOpen = TSSocketManager.shared.highestSocketState == OWSWebSocketStateOpen; + BOOL value = (OWSSignalService.sharedInstance.isCensorshipCircumventionManuallyActivated || (!OWSSignalService.sharedInstance.hasCensoredPhoneNumber && !isAnySocketOpen - && weakSelf.reachability.isReachable)); - BOOL isCensorshipCircumventionOn = NO; - if (OWSSignalService.sharedInstance.hasCensoredPhoneNumber) { - isCensorshipCircumventionOn = YES; - } else { - isCensorshipCircumventionOn = OWSSignalService.sharedInstance.isCensorshipCircumventionManuallyActivated; - } + && reachability.isReachable)); + return value; + }; [censorshipSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_ADVANCED_CENSORSHIP_CIRCUMVENTION", @"Label for the 'manual censorship circumvention' switch.") - isOn:isCensorshipCircumventionOn - isEnabled:isManualCensorshipCircumventionOnEnabled + isOnBlock:isCensorshipCircumventionOnBlock + isEnabledBlock:isManualCensorshipCircumventionOnEnabledBlock target:weakSelf selector:@selector(didToggleEnableCensorshipCircumventionSwitch:)]]; diff --git a/Signal/src/ViewControllers/AppSettings/BlockListViewController.m b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m index 5d6d7a82a..e2c62a0e0 100644 --- a/Signal/src/ViewControllers/AppSettings/BlockListViewController.m +++ b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import "BlockListViewController.h" @@ -91,21 +91,23 @@ NS_ASSUME_NONNULL_BEGIN @"BLOCK_LIST_BLOCKED_USERS_SECTION", @"Section header for users that have been blocked"); for (NSString *phoneNumber in blockedPhoneNumbers) { - [blockedContactsSection - addItem:[OWSTableItem - itemWithCustomCellBlock:^{ - ContactTableViewCell *cell = [ContactTableViewCell new]; - [cell configureWithRecipientId:phoneNumber]; - return cell; - } - customRowHeight:UITableViewAutomaticDimension - actionBlock:^{ - [BlockListUIUtils showUnblockPhoneNumberActionSheet:phoneNumber - fromViewController:weakSelf - blockingManager:helper.blockingManager - contactsManager:helper.contactsManager - completionBlock:nil]; - }]]; + [blockedContactsSection addItem:[OWSTableItem + itemWithCustomCellBlock:^{ + ContactTableViewCell *cell = [ContactTableViewCell new]; + [cell configureWithRecipientId:phoneNumber]; + return cell; + } + customRowHeight:UITableViewAutomaticDimension + actionBlock:^{ + [BlockListUIUtils + showUnblockPhoneNumberActionSheet:phoneNumber + fromViewController:weakSelf + blockingManager:helper.blockingManager + contactsManager:helper.contactsManager + completionBlock:^(BOOL isBlocked) { + [weakSelf updateTableContents]; + }]; + }]]; } [contents addSection:blockedContactsSection]; } @@ -142,7 +144,9 @@ NS_ASSUME_NONNULL_BEGIN displayName:groupName fromViewController:weakSelf blockingManager:helper.blockingManager - completionBlock:nil]; + completionBlock:^(BOOL isBlocked) { + [weakSelf updateTableContents]; + }]; }]]; } [contents addSection:blockedGroupsSection]; diff --git a/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m index 94a9ca09e..7b9f0cfa2 100644 --- a/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/NotificationSettingsViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import "NotificationSettingsViewController.h" @@ -56,7 +56,9 @@ @"Table cell switch label. When disabled, Signal will not play notification sounds while the app is in the " @"foreground."); [soundsSection addItem:[OWSTableItem switchItemWithText:inAppSoundsLabelText - isOn:[prefs soundInForeground] + isOnBlock:^{ + return [prefs soundInForeground]; + } target:weakSelf selector:@selector(didToggleSoundNotificationsSwitch:)]]; [contents addSection:soundsSection]; diff --git a/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m index 0dae62597..3ea0311aa 100644 --- a/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/OWSBackupSettingsViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import "OWSBackupSettingsViewController.h" @@ -117,7 +117,9 @@ NS_ASSUME_NONNULL_BEGIN addItem:[OWSTableItem switchItemWithText: NSLocalizedString(@"SETTINGS_BACKUP_ENABLING_SWITCH", @"Label for switch in settings that controls whether or not backup is enabled.") - isOn:isBackupEnabled + isOnBlock:^{ + return [OWSBackup.sharedManager isBackupEnabled]; + } target:self selector:@selector(isBackupEnabledDidChange:)]]; [contents addSection:enableSection]; @@ -187,6 +189,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)isBackupEnabledDidChange:(UISwitch *)sender { [OWSBackup.sharedManager setIsBackupEnabled:sender.isOn]; + + [self updateTableContents]; } #pragma mark - Events diff --git a/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m b/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m index de08936f7..3d0d8efc2 100644 --- a/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m +++ b/Signal/src/ViewControllers/AppSettings/PrivacySettingsTableViewController.m @@ -98,11 +98,14 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s = NSLocalizedString(@"SETTINGS_READ_RECEIPT", @"Label for the 'read receipts' setting."); readReceiptsSection.footerTitle = NSLocalizedString( @"SETTINGS_READ_RECEIPTS_SECTION_FOOTER", @"An explanation of the 'read receipts' setting."); - [readReceiptsSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_READ_RECEIPT", - @"Label for the 'read receipts' setting.") - isOn:[self.readReceiptManager areReadReceiptsEnabled] - target:weakSelf - selector:@selector(didToggleReadReceiptsSwitch:)]]; + [readReceiptsSection + addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_READ_RECEIPT", + @"Label for the 'read receipts' setting.") + isOnBlock:^{ + return [OWSReadReceiptManager.sharedManager areReadReceiptsEnabled]; + } + target:weakSelf + selector:@selector(didToggleReadReceiptsSwitch:)]]; [contents addSection:readReceiptsSection]; OWSTableSection *typingIndicatorsSection = [OWSTableSection new]; @@ -110,11 +113,14 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s = NSLocalizedString(@"SETTINGS_TYPING_INDICATORS", @"Label for the 'typing indicators' setting."); typingIndicatorsSection.footerTitle = NSLocalizedString( @"SETTINGS_TYPING_INDICATORS_FOOTER", @"An explanation of the 'typing indicators' setting."); - [typingIndicatorsSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_TYPING_INDICATORS", - @"Label for the 'typing indicators' setting.") - isOn:[self.typingIndicators areTypingIndicatorsEnabled] - target:weakSelf - selector:@selector(didToggleTypingIndicatorsSwitch:)]]; + [typingIndicatorsSection + addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_TYPING_INDICATORS", + @"Label for the 'typing indicators' setting.") + isOnBlock:^{ + return [SSKEnvironment.shared.typingIndicators areTypingIndicatorsEnabled]; + } + target:weakSelf + selector:@selector(didToggleTypingIndicatorsSwitch:)]]; [contents addSection:typingIndicatorsSection]; OWSTableSection *screenLockSection = [OWSTableSection new]; @@ -126,7 +132,9 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_SCREEN_LOCK_SWITCH_LABEL", @"Label for the 'enable screen lock' switch of the privacy settings.") - isOn:OWSScreenLock.sharedManager.isScreenLockEnabled + isOnBlock:^{ + return [OWSScreenLock.sharedManager isScreenLockEnabled]; + } target:self selector:@selector(isScreenLockEnabledDidChange:)]]; [contents addSection:screenLockSection]; @@ -150,10 +158,13 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s OWSTableSection *screenSecuritySection = [OWSTableSection new]; screenSecuritySection.headerTitle = NSLocalizedString(@"SETTINGS_SECURITY_TITLE", @"Section header"); screenSecuritySection.footerTitle = NSLocalizedString(@"SETTINGS_SCREEN_SECURITY_DETAIL", nil); - [screenSecuritySection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_SCREEN_SECURITY", @"") - isOn:[self.preferences screenSecurityIsEnabled] - target:weakSelf - selector:@selector(didToggleScreenSecuritySwitch:)]]; + [screenSecuritySection + addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_SCREEN_SECURITY", @"") + isOnBlock:^{ + return [Environment.shared.preferences screenSecurityIsEnabled]; + } + target:weakSelf + selector:@selector(didToggleScreenSecuritySwitch:)]]; [contents addSection:screenSecuritySection]; // Allow calls to connect directly vs. using TURN exclusively @@ -165,7 +176,9 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s [callingSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString( @"SETTINGS_CALLING_HIDES_IP_ADDRESS_PREFERENCE_TITLE", @"Table cell label") - isOn:[self.preferences doCallsHideIPAddress] + isOnBlock:^{ + return [Environment.shared.preferences doCallsHideIPAddress]; + } target:weakSelf selector:@selector(didToggleCallsHideIPAddressSwitch:)]]; [contents addSection:callingSection]; @@ -176,7 +189,9 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s addItem:[OWSTableItem switchItemWithText:NSLocalizedString( @"SETTINGS_PRIVACY_CALLKIT_SYSTEM_CALL_LOG_PREFERENCE_TITLE", @"Short table cell label") - isOn:[self.preferences isSystemCallLogEnabled] + isOnBlock:^{ + return [Environment.shared.preferences isSystemCallLogEnabled]; + } target:weakSelf selector:@selector(didToggleEnableSystemCallLogSwitch:)]]; callKitSection.footerTitle = NSLocalizedString( @@ -188,14 +203,19 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s = NSLocalizedString(@"SETTINGS_SECTION_CALL_KIT_DESCRIPTION", @"Settings table section footer."); [callKitSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_PRIVACY_CALLKIT_TITLE", @"Short table cell label") - isOn:[self.preferences isCallKitEnabled] + isOnBlock:^{ + return [Environment.shared.preferences isCallKitEnabled]; + } target:weakSelf selector:@selector(didToggleEnableCallKitSwitch:)]]; if (self.preferences.isCallKitEnabled) { [callKitSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_PRIVACY_CALLKIT_PRIVACY_TITLE", @"Label for 'CallKit privacy' preference") - isOn:![self.preferences isCallKitPrivacyEnabled] + isOnBlock:^{ + return (BOOL) ! + [Environment.shared.preferences isCallKitPrivacyEnabled]; + } target:weakSelf selector:@selector(didToggleEnableCallKitPrivacySwitch:)]]; } @@ -260,7 +280,7 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s UISwitch *cellSwitch = [UISwitch new]; cell.accessoryView = cellSwitch; - [cellSwitch setOn:weakSelf.preferences.shouldShowUnidentifiedDeliveryIndicators]; + [cellSwitch setOn:Environment.shared.preferences.shouldShowUnidentifiedDeliveryIndicators]; [cellSwitch addTarget:weakSelf action:@selector(didToggleUDShowIndicatorsSwitch:) forControlEvents:UIControlEventValueChanged]; @@ -290,7 +310,9 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s OWSTableSection *unidentifiedDeliveryUnrestrictedSection = [OWSTableSection new]; OWSTableItem *unrestrictedAccessItem = [OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_UNIDENTIFIED_DELIVERY_UNRESTRICTED_ACCESS", @"switch label") - isOn:weakSelf.udManager.shouldAllowUnrestrictedAccessLocal + isOnBlock:^{ + return [SSKEnvironment.shared.udManager shouldAllowUnrestrictedAccessLocal]; + } target:weakSelf selector:@selector(didToggleUDUnrestrictedAccessSwitch:)]; [unidentifiedDeliveryUnrestrictedSection addItem:unrestrictedAccessItem]; @@ -313,7 +335,9 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s [linkPreviewsSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_LINK_PREVIEWS", @"Setting for enabling & disabling link previews.") - isOn:SSKPreferences.areLinkPreviewsEnabled + isOnBlock:^{ + return [SSKPreferences areLinkPreviewsEnabled]; + } target:weakSelf selector:@selector(didToggleLinkPreviewsEnabled:)]]; linkPreviewsSection.headerTitle = NSLocalizedString( diff --git a/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m index 4df03214e..922bf8218 100644 --- a/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m @@ -1122,6 +1122,7 @@ const CGFloat kIconViewLength = 24; BOOL isCurrentlyBlocked = [self.blockingManager isThreadBlocked:self.thread]; + __weak OWSConversationSettingsViewController *weakSelf = self; if (blockConversationSwitch.isOn) { OWSAssertDebug(!isCurrentlyBlocked); if (isCurrentlyBlocked) { @@ -1135,6 +1136,8 @@ const CGFloat kIconViewLength = 24; completionBlock:^(BOOL isBlocked) { // Update switch state if user cancels action. blockConversationSwitch.on = isBlocked; + + [weakSelf updateTableContents]; }]; } else { @@ -1149,6 +1152,8 @@ const CGFloat kIconViewLength = 24; completionBlock:^(BOOL isBlocked) { // Update switch state if user cancels action. blockConversationSwitch.on = isBlocked; + + [weakSelf updateTableContents]; }]; } } diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.h b/SignalMessaging/ViewControllers/OWSTableViewController.h index bbf69e576..bc24cc005 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.h +++ b/SignalMessaging/ViewControllers/OWSTableViewController.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import @@ -47,6 +47,7 @@ extern const CGFloat kOWSTable_DefaultCellHeight; typedef void (^OWSTableActionBlock)(void); typedef void (^OWSTableSubPageBlock)(UIViewController *viewController); typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(void); +typedef BOOL (^OWSTableSwitchBlock)(void); @interface OWSTableItem : NSObject @@ -103,11 +104,14 @@ typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(void); + (OWSTableItem *)longDisclosureItemWithText:(NSString *)text actionBlock:(nullable OWSTableActionBlock)actionBlock; -+ (OWSTableItem *)switchItemWithText:(NSString *)text isOn:(BOOL)isOn target:(id)target selector:(SEL)selector; ++ (OWSTableItem *)switchItemWithText:(NSString *)text + isOnBlock:(OWSTableSwitchBlock)isOnBlock + target:(id)target + selector:(SEL)selector; + (OWSTableItem *)switchItemWithText:(NSString *)text - isOn:(BOOL)isOn - isEnabled:(BOOL)isEnabled + isOnBlock:(OWSTableSwitchBlock)isOnBlock + isEnabledBlock:(OWSTableSwitchBlock)isEnabledBlock target:(id)target selector:(SEL)selector; diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.m b/SignalMessaging/ViewControllers/OWSTableViewController.m index 2b7c7a882..e6caf9962 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.m +++ b/SignalMessaging/ViewControllers/OWSTableViewController.m @@ -366,14 +366,23 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; return item; } -+ (OWSTableItem *)switchItemWithText:(NSString *)text isOn:(BOOL)isOn target:(id)target selector:(SEL)selector ++ (OWSTableItem *)switchItemWithText:(NSString *)text + isOnBlock:(OWSTableSwitchBlock)isOnBlock + target:(id)target + selector:(SEL)selector { - return [self switchItemWithText:text isOn:isOn isEnabled:YES target:target selector:selector]; + return [self switchItemWithText:text + isOnBlock:(OWSTableSwitchBlock)isOnBlock + isEnabledBlock:^{ + return YES; + } + target:target + selector:selector]; } + (OWSTableItem *)switchItemWithText:(NSString *)text - isOn:(BOOL)isOn - isEnabled:(BOOL)isEnabled + isOnBlock:(OWSTableSwitchBlock)isOnBlock + isEnabledBlock:(OWSTableSwitchBlock)isEnabledBlock target:(id)target selector:(SEL)selector { @@ -389,9 +398,9 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; UISwitch *cellSwitch = [UISwitch new]; cell.accessoryView = cellSwitch; - [cellSwitch setOn:isOn]; + [cellSwitch setOn:isOnBlock()]; [cellSwitch addTarget:weakTarget action:selector forControlEvents:UIControlEventValueChanged]; - cellSwitch.enabled = isEnabled; + cellSwitch.enabled = isEnabledBlock(); cell.selectionStyle = UITableViewCellSelectionStyleNone;