diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 9b92ba729..b796eab29 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -1026,9 +1026,19 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, updateRemoteVideoLayout() } - internal func dismissIfPossible(shouldDelay: Bool, ignoreNag: Bool = false, completion: (() -> Swift.Void)? = nil) { + internal func dismissIfPossible(shouldDelay: Bool, ignoreNag ignoreNagParam: Bool = false, completion: (() -> Swift.Void)? = nil) { callUIAdapter.audioService.delegate = nil + let ignoreNag: Bool = { + // Nothing to nag about on iOS11 + if #available(iOS 11, *) { + return true + } else { + // otherwise on iOS10, nag as specified + return ignoreNagParam + } + }() + if hasDismissed { // Don't dismiss twice. return diff --git a/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m b/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m index 628e6501e..04a83c3e2 100644 --- a/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m +++ b/Signal/src/ViewControllers/NotificationSettingsOptionsViewController.m @@ -1,8 +1,10 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "NotificationSettingsOptionsViewController.h" +#import "Signal-Swift.h" +#import "SignalApp.h" #import @implementation NotificationSettingsOptionsViewController @@ -48,6 +50,10 @@ - (void)setNotificationType:(NotificationType)notificationType { [Environment.preferences setNotificationPreviewType:notificationType]; + + // rebuild callUIAdapter since notification configuration changed. + [SignalApp.sharedApp.callService createCallUIAdapter]; + [self.navigationController popViewControllerAnimated:YES]; } diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.m b/Signal/src/ViewControllers/NotificationSettingsViewController.m index df653f7e9..fdd986d69 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/NotificationSettingsViewController.m @@ -56,7 +56,7 @@ [contents addSection:soundsSection]; OWSTableSection *backgroundSection = [OWSTableSection new]; - backgroundSection.headerTitle = NSLocalizedString(@"NOTIFICATIONS_SECTION_BACKGROUND", nil); + backgroundSection.headerTitle = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_TITLE", @"table section header"); [backgroundSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"UITableViewCellStyleValue1"]; @@ -74,6 +74,8 @@ [NotificationSettingsOptionsViewController new]; [weakSelf.navigationController pushViewController:vc animated:YES]; }]]; + backgroundSection.footerTitle + = NSLocalizedString(@"SETTINGS_NOTIFICATION_CONTENT_DESCRIPTION", @"table section footer"); [contents addSection:backgroundSection]; OWSTableSection *inAppSection = [OWSTableSection new]; diff --git a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m b/Signal/src/ViewControllers/PrivacySettingsTableViewController.m index 6dcf6ff7c..c57ed4b5d 100644 --- a/Signal/src/ViewControllers/PrivacySettingsTableViewController.m +++ b/Signal/src/ViewControllers/PrivacySettingsTableViewController.m @@ -80,7 +80,19 @@ NS_ASSUME_NONNULL_BEGIN selector:@selector(didToggleCallsHideIPAddressSwitch:)]]; [contents addSection:callingSection]; - if ([UIDevice currentDevice].supportsCallKit) { + if (@available(iOS 11, *)) { + OWSTableSection *callKitSection = [OWSTableSection new]; + [callKitSection + addItem:[OWSTableItem switchItemWithText:NSLocalizedString( + @"SETTINGS_PRIVACY_CALLKIT_SYSTEM_CALL_LOG_PREFERENCE_TITLE", + @"Short table cell label") + isOn:[Environment.preferences isSystemCallLogEnabled] + target:weakSelf + selector:@selector(didToggleEnableSystemCallLogSwitch:)]]; + callKitSection.footerTitle = NSLocalizedString( + @"SETTINGS_PRIVACY_CALLKIT_SYSTEM_CALL_LOG_PREFERENCE_DESCRIPTION", @"Settings table section footer."); + [contents addSection:callKitSection]; + } else if (@available(iOS 10, *)) { OWSTableSection *callKitSection = [OWSTableSection new]; callKitSection.footerTitle = NSLocalizedString(@"SETTINGS_SECTION_CALL_KIT_DESCRIPTION", @"Settings table section footer."); @@ -89,7 +101,7 @@ NS_ASSUME_NONNULL_BEGIN isOn:[Environment.preferences isCallKitEnabled] target:weakSelf selector:@selector(didToggleEnableCallKitSwitch:)]]; - if (Environment.preferences.isCallKitEnabled && !Environment.preferences.isCallKitPrivacyAutoDisabled) { + if (Environment.preferences.isCallKitEnabled) { [callKitSection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"SETTINGS_PRIVACY_CALLKIT_PRIVACY_TITLE", @"Label for 'CallKit privacy' preference") @@ -173,17 +185,32 @@ NS_ASSUME_NONNULL_BEGIN [Environment.preferences setDoCallsHideIPAddress:enabled]; } +- (void)didToggleEnableSystemCallLogSwitch:(UISwitch *)sender +{ + DDLogInfo(@"%@ user toggled call kit preference: %@", self.logTag, (sender.isOn ? @"ON" : @"OFF")); + [[Environment current].preferences setIsSystemCallLogEnabled:sender.isOn]; + + // rebuild callUIAdapter since CallKit configuration changed. + [SignalApp.sharedApp.callService createCallUIAdapter]; +} + - (void)didToggleEnableCallKitSwitch:(UISwitch *)sender { DDLogInfo(@"%@ user toggled call kit preference: %@", self.logTag, (sender.isOn ? @"ON" : @"OFF")); [[Environment current].preferences setIsCallKitEnabled:sender.isOn]; + // rebuild callUIAdapter since CallKit vs not changed. [SignalApp.sharedApp.callService createCallUIAdapter]; + + // Show/Hide dependent switch: CallKit privacy [self updateTableContents]; } - (void)didToggleEnableCallKitPrivacySwitch:(UISwitch *)sender { DDLogInfo(@"%@ user toggled call kit privacy preference: %@", self.logTag, (sender.isOn ? @"ON" : @"OFF")); [[Environment current].preferences setIsCallKitPrivacyEnabled:!sender.isOn]; + + // rebuild callUIAdapter since CallKit configuration changed. + [SignalApp.sharedApp.callService createCallUIAdapter]; } #pragma mark - Log util diff --git a/Signal/src/call/CallAudioService.swift b/Signal/src/call/CallAudioService.swift index 4560ca631..a841bab60 100644 --- a/Signal/src/call/CallAudioService.swift +++ b/Signal/src/call/CallAudioService.swift @@ -123,8 +123,8 @@ protocol CallAudioServiceDelegate: class { super.init() - // This fails when someone toggles iOS Call Integration - SwiftSingletons.register(self) + // We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings + // SwiftSingletons.register(self) // Configure audio session so we don't prompt user with Record permission until call is connected. diff --git a/Signal/src/call/Speakerbox/CallKitCallManager.swift b/Signal/src/call/Speakerbox/CallKitCallManager.swift index fff993181..545e08c80 100644 --- a/Signal/src/call/Speakerbox/CallKitCallManager.swift +++ b/Signal/src/call/Speakerbox/CallKitCallManager.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import UIKit @@ -18,26 +18,30 @@ import SignalServiceKit final class CallKitCallManager: NSObject { let callController = CXCallController() + let showNamesOnCallScreen: Bool static let kAnonymousCallHandlePrefix = "Signal:" - override required init() { + required init(showNamesOnCallScreen: Bool) { AssertIsOnMainThread() + self.showNamesOnCallScreen = showNamesOnCallScreen super.init() - SwiftSingletons.register(self) + // We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings + // SwiftSingletons.register(self) } // MARK: Actions func startCall(_ call: SignalCall) { var handle: CXHandle - if Environment.current().preferences.isCallKitPrivacyEnabled() { + + if showNamesOnCallScreen { + handle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber) + } else { let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.localId.uuidString handle = CXHandle(type: .generic, value: callKitId) TSStorageManager.shared().setPhoneNumber(call.remotePhoneNumber, forCallKitId:callKitId) - } else { - handle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber) } let startCallAction = CXStartCallAction(call: call.localId, handle: handle) diff --git a/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift b/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift index b1531400a..d96fdd7f2 100644 --- a/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift +++ b/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift @@ -24,14 +24,15 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { internal let callService: CallService internal let notificationsAdapter: CallNotificationsAdapter internal let contactsManager: OWSContactsManager + private let showNamesOnCallScreen: Bool private let provider: CXProvider - let audioActivity: AudioActivity + private let audioActivity: AudioActivity // CallKit handles incoming ringer stop/start for us. Yay! let hasManualRinger = false // The app's provider configuration, representing its CallKit capabilities - static var providerConfiguration: CXProviderConfiguration { + class func buildProviderConfiguration(useSystemCallLog: Bool) -> CXProviderConfiguration { let localizedName = NSLocalizedString("APPLICATION_NAME", comment: "Name of application") let providerConfiguration = CXProviderConfiguration(localizedName: localizedName) @@ -51,27 +52,35 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { // system contact, if possible (iOS 11 or later). if #available(iOS 11.0, *) { - providerConfiguration.includesCallsInRecents = false + providerConfiguration.includesCallsInRecents = useSystemCallLog + } else { + // not configurable for iOS10+ + assert(useSystemCallLog) } return providerConfiguration } - init(callService: CallService, contactsManager: OWSContactsManager, notificationsAdapter: CallNotificationsAdapter) { + init(callService: CallService, contactsManager: OWSContactsManager, notificationsAdapter: CallNotificationsAdapter, showNamesOnCallScreen: Bool, useSystemCallLog: Bool) { AssertIsOnMainThread() Logger.debug("\(self.TAG) \(#function)") - self.callManager = CallKitCallManager() + self.callManager = CallKitCallManager(showNamesOnCallScreen: showNamesOnCallScreen) self.callService = callService self.contactsManager = contactsManager self.notificationsAdapter = notificationsAdapter - self.provider = CXProvider(configuration: type(of: self).providerConfiguration) + + let providerConfiguration = type(of: self).buildProviderConfiguration(useSystemCallLog: useSystemCallLog) + self.provider = CXProvider(configuration: providerConfiguration) + self.audioActivity = AudioActivity(audioDescription: "[CallKitCallUIAdaptee]") + self.showNamesOnCallScreen = showNamesOnCallScreen super.init() - SwiftSingletons.register(self) + // We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings + // SwiftSingletons.register(self) self.provider.setDelegate(self, queue: nil) } @@ -116,14 +125,15 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { // Construct a CXCallUpdate describing the incoming call, including the caller. let update = CXCallUpdate() - if Environment.current().preferences.isCallKitPrivacyEnabled() { + + if showNamesOnCallScreen { + update.localizedCallerName = self.contactsManager.stringForConversationTitle(withPhoneIdentifier: call.remotePhoneNumber) + update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber) + } else { let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.localId.uuidString update.remoteHandle = CXHandle(type: .generic, value: callKitId) TSStorageManager.shared().setPhoneNumber(call.remotePhoneNumber, forCallKitId: callKitId) update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled") - } else { - update.localizedCallerName = self.contactsManager.stringForConversationTitle(withPhoneIdentifier: call.remotePhoneNumber) - update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber) } update.hasVideo = call.hasLocalVideo @@ -258,8 +268,9 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { action.fulfill() self.provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil) - if Environment.current().preferences.isCallKitPrivacyEnabled() { - // Update the name used in the CallKit UI for outgoing calls. + // Update the name used in the CallKit UI for outgoing calls when the user prefers not to show names + // in ther notifications + if !showNamesOnCallScreen { let update = CXCallUpdate() update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled") diff --git a/Signal/src/call/UserInterface/CallUIAdapter.swift b/Signal/src/call/UserInterface/CallUIAdapter.swift index df518ff1f..3956b1a4f 100644 --- a/Signal/src/call/UserInterface/CallUIAdapter.swift +++ b/Signal/src/call/UserInterface/CallUIAdapter.swift @@ -91,9 +91,21 @@ extension CallUIAdaptee { // So we use the non-CallKit call UI. Logger.info("\(TAG) choosing non-callkit adaptee for simulator.") adaptee = NonCallKitCallUIAdaptee(callService: callService, notificationsAdapter: notificationsAdapter) + } else if #available(iOS 11, *) { + Logger.info("\(TAG) choosing callkit adaptee for iOS11+") + let showNames = Environment.preferences().notificationPreviewType() != .noNameNoPreview + let useSystemCallLog = Environment.preferences().isSystemCallLogEnabled() + + adaptee = CallKitCallUIAdaptee(callService: callService, contactsManager: contactsManager, notificationsAdapter: notificationsAdapter, showNamesOnCallScreen: showNames, useSystemCallLog: useSystemCallLog) } else if #available(iOS 10.0, *), Environment.current().preferences.isCallKitEnabled() { - Logger.info("\(TAG) choosing callkit adaptee for iOS10+") - adaptee = CallKitCallUIAdaptee(callService: callService, contactsManager: contactsManager, notificationsAdapter: notificationsAdapter) + Logger.info("\(TAG) choosing callkit adaptee for iOS10") + let hideNames = Environment.preferences().isCallKitPrivacyEnabled() || Environment.preferences().notificationPreviewType() == .noNameNoPreview + let showNames = !hideNames + + // All CallKit calls use the system call log on iOS10 + let useSystemCallLog = true + + adaptee = CallKitCallUIAdaptee(callService: callService, contactsManager: contactsManager, notificationsAdapter: notificationsAdapter, showNamesOnCallScreen: showNames, useSystemCallLog: useSystemCallLog) } else { Logger.info("\(TAG) choosing non-callkit adaptee") adaptee = NonCallKitCallUIAdaptee(callService: callService, notificationsAdapter: notificationsAdapter) @@ -103,7 +115,8 @@ extension CallUIAdaptee { super.init() - SwiftSingletons.register(self) + // We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings + // SwiftSingletons.register(self) callService.addObserverAndSyncState(observer: self) } diff --git a/Signal/src/environment/NotificationsManager.m b/Signal/src/environment/NotificationsManager.m index 03d660b0b..5d2fc8271 100644 --- a/Signal/src/environment/NotificationsManager.m +++ b/Signal/src/environment/NotificationsManager.m @@ -112,10 +112,8 @@ } case NotificationNameNoPreview: case NotificationNamePreview: { - alertMessage = (([UIDevice currentDevice].supportsCallKit && - [[Environment current].preferences isCallKitPrivacyEnabled]) - ? [CallStrings missedCallNotificationBodyWithoutCallerName] - : [NSString stringWithFormat:[CallStrings missedCallNotificationBodyWithCallerName], callerName]); + alertMessage = + [NSString stringWithFormat:[CallStrings missedCallNotificationBodyWithCallerName], callerName]; break; } } @@ -152,12 +150,8 @@ } case NotificationNameNoPreview: case NotificationNamePreview: { - alertMessage = (([UIDevice currentDevice].supportsCallKit && - [[Environment current].preferences isCallKitPrivacyEnabled]) - ? [CallStrings missedCallWithIdentityChangeNotificationBodyWithoutCallerName] - : [NSString - stringWithFormat:[CallStrings missedCallWithIdentityChangeNotificationBodyWithCallerName], - callerName]); + alertMessage = [NSString + stringWithFormat:[CallStrings missedCallWithIdentityChangeNotificationBodyWithCallerName], callerName]; break; } } @@ -193,12 +187,8 @@ } case NotificationNameNoPreview: case NotificationNamePreview: { - alertMessage = (([UIDevice currentDevice].supportsCallKit && - [[Environment current].preferences isCallKitPrivacyEnabled]) - ? [CallStrings missedCallWithIdentityChangeNotificationBodyWithoutCallerName] - : [NSString - stringWithFormat:[CallStrings missedCallWithIdentityChangeNotificationBodyWithCallerName], - callerName]); + alertMessage = [NSString + stringWithFormat:[CallStrings missedCallWithIdentityChangeNotificationBodyWithCallerName], callerName]; break; } } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 0ae24fd8f..bfc1dc1bb 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1147,10 +1147,7 @@ "NOTIFICATIONS_FOOTER_WARNING" = "Due to known bugs in Apple's push framework, message previews will only be shown if the message is retrieved within 30 seconds after being sent. The application badge might be inaccurate as a result."; /* No comment provided by engineer. */ -"NOTIFICATIONS_NONE" = "No name or message"; - -/* No comment provided by engineer. */ -"NOTIFICATIONS_SECTION_BACKGROUND" = "Background Notifications"; +"NOTIFICATIONS_NONE" = "No Name or Content"; /* No comment provided by engineer. */ "NOTIFICATIONS_SECTION_INAPP" = "In-App Notifications"; @@ -1159,10 +1156,10 @@ "NOTIFICATIONS_SECTION_SOUNDS" = "Sounds"; /* No comment provided by engineer. */ -"NOTIFICATIONS_SENDER_AND_MESSAGE" = "Sender name & message"; +"NOTIFICATIONS_SENDER_AND_MESSAGE" = "Name and Content"; /* No comment provided by engineer. */ -"NOTIFICATIONS_SENDER_ONLY" = "Sender name only"; +"NOTIFICATIONS_SENDER_ONLY" = "Name Only"; /* No comment provided by engineer. */ "NOTIFICATIONS_SHOW" = "Show"; @@ -1575,12 +1572,24 @@ /* Title for settings activity */ "SETTINGS_NAV_BAR_TITLE" = "Settings"; +/* table section footer */ +"SETTINGS_NOTIFICATION_CONTENT_DESCRIPTION" = "Call and Message notifications can appear while your phone is locked. You may wish to limit what is shown in these notifications."; + +/* table section header */ +"SETTINGS_NOTIFICATION_CONTENT_TITLE" = "Notification Content"; + /* No comment provided by engineer. */ "SETTINGS_NOTIFICATIONS" = "Notifications"; /* Label for 'CallKit privacy' preference */ "SETTINGS_PRIVACY_CALLKIT_PRIVACY_TITLE" = "Show Caller's Name & Number"; +/* Settings table section footer. */ +"SETTINGS_PRIVACY_CALLKIT_SYSTEM_CALL_LOG_PREFERENCE_DESCRIPTION" = "Disabling this will prevent calls from appearing in the \"Recents\" list in the iOS Phone app."; + +/* Short table cell label */ +"SETTINGS_PRIVACY_CALLKIT_SYSTEM_CALL_LOG_PREFERENCE_TITLE" = "System Call Logs"; + /* Short table cell label */ "SETTINGS_PRIVACY_CALLKIT_TITLE" = "iOS Call Integration"; diff --git a/SignalMessaging/utils/OWSPreferences.h b/SignalMessaging/utils/OWSPreferences.h index 6daaf8656..f68aeb28e 100644 --- a/SignalMessaging/utils/OWSPreferences.h +++ b/SignalMessaging/utils/OWSPreferences.h @@ -59,8 +59,14 @@ extern NSString *const OWSPreferencesKeyEnableDebugLog; #pragma mark Callkit +- (BOOL)isSystemCallLogEnabled; +- (void)setIsSystemCallLogEnabled:(BOOL)flag; + +#pragma mark - Legacy CallKit settings + - (BOOL)isCallKitEnabled; - (void)setIsCallKitEnabled:(BOOL)flag; + // Returns YES IFF isCallKitEnabled has been set by user. - (BOOL)isCallKitEnabledSet; @@ -68,7 +74,6 @@ extern NSString *const OWSPreferencesKeyEnableDebugLog; - (void)setIsCallKitPrivacyEnabled:(BOOL)flag; // Returns YES IFF isCallKitPrivacyEnabled has been set by user. - (BOOL)isCallKitPrivacySet; -- (BOOL)isCallKitPrivacyAutoDisabled; #pragma mark direct call connectivity (non-TURN) diff --git a/SignalMessaging/utils/OWSPreferences.m b/SignalMessaging/utils/OWSPreferences.m index 4de2c2d0d..d61369b23 100644 --- a/SignalMessaging/utils/OWSPreferences.m +++ b/SignalMessaging/utils/OWSPreferences.m @@ -26,6 +26,7 @@ NSString *const OWSPreferencesKeyCallsHideIPAddress = @"CallsHideIPAddress"; NSString *const OWSPreferencesKeyHasDeclinedNoContactsView = @"hasDeclinedNoContactsView"; NSString *const OWSPreferencesKeyIOSUpgradeNagDate = @"iOSUpgradeNagDate"; NSString *const OWSPreferencesKey_IsReadyForAppExtensions = @"isReadyForAppExtensions_5"; +NSString *const OWSPreferencesKeySystemCallLogEnabled = @"OWSPreferencesKeySystemCallLogEnabled"; @implementation OWSPreferences @@ -173,46 +174,96 @@ NSString *const OWSPreferencesKey_IsReadyForAppExtensions = @"isReadyForAppExten #pragma mark CallKit +- (BOOL)isSystemCallLogEnabled +{ + if (@available(iOS 11, *)) { + // do nothing + } else { + OWSFail(@"%@ Call Logging can only be configured on iOS11+", self.logTag); + return NO; + } + + NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeySystemCallLogEnabled]; + + if (preference) { + return preference.boolValue; + } else { + // For legacy users, who may have previously intentionally disabled CallKit because they + // didn't want their calls showing up in the call log, we want to disable call logging + NSNumber *callKitPreference = [self tryGetValueForKey:OWSPreferencesKeyCallKitEnabled]; + if (callKitPreference && !callKitPreference.boolValue) { + // user expclitily opted out of callKit, so disable system call logging. + return NO; + } + } + + // For everyone else, including new users, enable by default. + return YES; +} + +- (void)setIsSystemCallLogEnabled:(BOOL)flag +{ + if (@available(iOS 11, *)) { + // do nothing + } else { + OWSFail(@"%@ Call Logging can only be configured on iOS11+", self.logTag); + return; + } + + [self setValueForKey:OWSPreferencesKeySystemCallLogEnabled toValue:@(flag)]; +} + +// In iOS 10.2.1, Apple fixed a bug wherein call history was backed up to iCloud. +// +// See: https://support.apple.com/en-us/HT207482 +// +// In iOS 11, Apple introduced a property CXProviderConfiguration.includesCallsInRecents +// that allows us to prevent Signal calls made with CallKit from showing up in the device's +// call history. +// +// Therefore in versions of iOS after 11, we have no need of call privacy. +#pragma mark Legacy CallKit + - (BOOL)isCallKitEnabled { + if (@available(iOS 11, *)) { + OWSFail(@"%@ CallKit privacy is irrelevant for iOS11+", self.logTag); + return NO; + } + NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeyCallKitEnabled]; return preference ? [preference boolValue] : YES; } - (void)setIsCallKitEnabled:(BOOL)flag { + if (@available(iOS 11, *)) { + OWSFail(@"%@ CallKit privacy is irrelevant for iOS11+", self.logTag); + return; + } + [self setValueForKey:OWSPreferencesKeyCallKitEnabled toValue:@(flag)]; + OWSFail(@"Rev callUIAdaptee to get new setting"); } - (BOOL)isCallKitEnabledSet { - NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeyCallKitEnabled]; - return preference != nil; -} - -- (BOOL)isCallKitPrivacyAutoDisabled -{ - // In iOS 10.2.1, Apple fixed a bug wherein call history was backed up to iCloud. - // - // See: https://support.apple.com/en-us/HT207482 - // - // In iOS 11, Apple introduced a property CXProviderConfiguration.includesCallsInRecents - // that allows us to prevent Signal calls made with CallKit from showing up in the device's - // call history. - // - // Therefore in versions of iOS after 11, we have no need of call privacy. - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(11, 0)) { - return YES; - } else { + if (@available(iOS 11, *)) { + OWSFail(@"%@ CallKit privacy is irrelevant for iOS11+", self.logTag); return NO; } + + NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeyCallKitEnabled]; + return preference != nil; } - (BOOL)isCallKitPrivacyEnabled { - if ([self isCallKitPrivacyAutoDisabled]) { + if (@available(iOS 11, *)) { + OWSFail(@"%@ CallKit privacy is irrelevant for iOS11+", self.logTag); return NO; } + NSNumber *_Nullable preference = [self tryGetValueForKey:OWSPreferencesKeyCallKitPrivacyEnabled]; if (preference) { return [preference boolValue]; @@ -224,11 +275,21 @@ NSString *const OWSPreferencesKey_IsReadyForAppExtensions = @"isReadyForAppExten - (void)setIsCallKitPrivacyEnabled:(BOOL)flag { + if (@available(iOS 11, *)) { + OWSFail(@"%@ CallKit privacy is irrelevant for iOS11+", self.logTag); + return; + } + [self setValueForKey:OWSPreferencesKeyCallKitPrivacyEnabled toValue:@(flag)]; } - (BOOL)isCallKitPrivacySet { + if (@available(iOS 11, *)) { + OWSFail(@"%@ CallKit privacy is irrelevant for iOS11+", self.logTag); + return NO; + } + NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeyCallKitPrivacyEnabled]; return preference != nil; }