mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
users can opt out of CallKit
// FREEBIE
This commit is contained in:
parent
d8df4b9e35
commit
2a9aa4c852
9 changed files with 178 additions and 53 deletions
|
@ -204,6 +204,7 @@ import Foundation
|
|||
}
|
||||
|
||||
private func setAudioSession(category: String) {
|
||||
// FIXME Why this default mode? It doesn't work with e.g. "SoloAmbient", causing `AVAudioSession.sharedInstance().setCategory(category, mode: mode, options: options)` to err
|
||||
setAudioSession(category:category,
|
||||
mode:AVAudioSessionModeVoiceChat,
|
||||
options:AVAudioSessionCategoryOptions(rawValue: 0))
|
||||
|
|
|
@ -100,9 +100,13 @@ protocol CallServiceObserver: class {
|
|||
|
||||
// MARK: Dependencies
|
||||
|
||||
let accountManager: AccountManager
|
||||
let messageSender: MessageSender
|
||||
var callUIAdapter: CallUIAdapter!
|
||||
private let accountManager: AccountManager
|
||||
private let messageSender: MessageSender
|
||||
private let contactsManager: OWSContactsManager
|
||||
private let notificationsAdapter: CallNotificationsAdapter
|
||||
|
||||
// Exposed by environment.m
|
||||
internal var callUIAdapter: CallUIAdapter!
|
||||
|
||||
// MARK: Class
|
||||
|
||||
|
@ -179,11 +183,13 @@ protocol CallServiceObserver: class {
|
|||
|
||||
required init(accountManager: AccountManager, contactsManager: OWSContactsManager, messageSender: MessageSender, notificationsAdapter: CallNotificationsAdapter) {
|
||||
self.accountManager = accountManager
|
||||
self.contactsManager = contactsManager
|
||||
self.messageSender = messageSender
|
||||
self.notificationsAdapter = notificationsAdapter
|
||||
|
||||
super.init()
|
||||
|
||||
self.callUIAdapter = CallUIAdapter(callService: self, contactsManager: contactsManager, notificationsAdapter: notificationsAdapter)
|
||||
self.createCallUIAdapter()
|
||||
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector:#selector(didEnterBackground),
|
||||
|
@ -213,6 +219,16 @@ protocol CallServiceObserver: class {
|
|||
self.updateIsVideoEnabled()
|
||||
}
|
||||
|
||||
public func createCallUIAdapter() {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
if self.call != nil {
|
||||
Logger.warn("\(TAG) ending current call in \(#function). Did user toggle callkit preference while in a call?")
|
||||
self.terminateCall()
|
||||
}
|
||||
self.callUIAdapter = CallUIAdapter(callService: self, contactsManager: self.contactsManager, notificationsAdapter: self.notificationsAdapter)
|
||||
}
|
||||
|
||||
// MARK: - Class Methods
|
||||
|
||||
// MARK: Notifications
|
||||
|
|
|
@ -10,14 +10,12 @@ import Foundation
|
|||
@objc class OutboundCallInitiator: NSObject {
|
||||
let TAG = "[OutboundCallInitiator]"
|
||||
|
||||
let callUIAdapter: CallUIAdapter
|
||||
let redphoneManager: PhoneManager
|
||||
let contactsManager: OWSContactsManager
|
||||
let contactsUpdater: ContactsUpdater
|
||||
|
||||
init(redphoneManager: PhoneManager, callUIAdapter: CallUIAdapter, contactsManager: OWSContactsManager, contactsUpdater: ContactsUpdater) {
|
||||
init(redphoneManager: PhoneManager, contactsManager: OWSContactsManager, contactsUpdater: ContactsUpdater) {
|
||||
self.redphoneManager = redphoneManager
|
||||
self.callUIAdapter = callUIAdapter
|
||||
|
||||
self.contactsManager = contactsManager
|
||||
self.contactsUpdater = contactsUpdater
|
||||
|
@ -93,6 +91,14 @@ import Foundation
|
|||
}
|
||||
|
||||
private func initiateWebRTCAudioCall(recipientId: String) -> Bool {
|
||||
// Rather than an init-assigned dependency property, we access `callUIAdapter` via Environment
|
||||
// because it can change after app launch due to user settings
|
||||
guard let callUIAdapter = Environment.getCurrent().callUIAdapter else {
|
||||
assertionFailure()
|
||||
Logger.error("\(TAG) can't initiate call because callUIAdapter is nil")
|
||||
return false
|
||||
}
|
||||
|
||||
callUIAdapter.startAndShowOutgoingCall(recipientId: recipientId)
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -77,11 +77,11 @@ 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 10.0, *) {
|
||||
} else if #available(iOS 10.0, *), Environment.getCurrent().preferences.isCallKitEnabled() {
|
||||
Logger.info("\(TAG) choosing callkit adaptee for iOS10+")
|
||||
adaptee = CallKitCallUIAdaptee(callService: callService, notificationsAdapter: notificationsAdapter)
|
||||
} else {
|
||||
Logger.info("\(TAG) choosing non-callkit adaptee for older iOS")
|
||||
Logger.info("\(TAG) choosing non-callkit adaptee")
|
||||
adaptee = NonCallKitCallUIAdaptee(callService: callService, notificationsAdapter: notificationsAdapter)
|
||||
}
|
||||
|
||||
|
|
|
@ -183,11 +183,9 @@ static Environment *environment = nil;
|
|||
@synchronized (self) {
|
||||
if (!_outboundCallInitiator) {
|
||||
OWSAssert(self.phoneManager);
|
||||
OWSAssert(self.callUIAdapter);
|
||||
OWSAssert(self.contactsManager);
|
||||
OWSAssert(self.contactsUpdater);
|
||||
_outboundCallInitiator = [[OutboundCallInitiator alloc] initWithRedphoneManager:self.phoneManager
|
||||
callUIAdapter:self.callUIAdapter
|
||||
contactsManager:self.contactsManager
|
||||
contactsUpdater:self.contactsUpdater];
|
||||
}
|
||||
|
|
|
@ -64,9 +64,18 @@ extern NSString *const PropertyListPreferencesKeyEnableDebugLog;
|
|||
- (nullable NSString *)lastRanVersion;
|
||||
- (NSString *)setAndGetCurrentVersion;
|
||||
|
||||
#pragma mark - Calling
|
||||
|
||||
#pragma mark WebRTC
|
||||
|
||||
- (BOOL)isWebRTCEnabled;
|
||||
- (void)setIsWebRTCEnabled:(BOOL)flag;
|
||||
|
||||
#pragma mark Callkit
|
||||
|
||||
- (BOOL)isCallKitEnabled;
|
||||
- (void)setIsCallKitEnabled:(BOOL)flag;
|
||||
|
||||
#pragma mark - Block on Identity Change
|
||||
|
||||
- (BOOL)shouldBlockOnIdentityChange;
|
||||
|
|
|
@ -24,6 +24,7 @@ NSString *const PropertyListPreferencesKeyHasRegisteredVoipPush = @"VOIPPushEnab
|
|||
NSString *const PropertyListPreferencesKeyLastRecordedPushToken = @"LastRecordedPushToken";
|
||||
NSString *const PropertyListPreferencesKeyLastRecordedVoipToken = @"LastRecordedVoipToken";
|
||||
NSString *const PropertyListPreferencesKeyWebRTCEnabled = @"WebRTCEnabled";
|
||||
NSString *const PropertyListPreferencesKeyCallKitEnabled = @"CallKitEnabled";
|
||||
|
||||
@implementation PropertyListPreferences
|
||||
|
||||
|
@ -79,13 +80,6 @@ NSString *const PropertyListPreferencesKeyWebRTCEnabled = @"WebRTCEnabled";
|
|||
return preference ? [preference boolValue] : YES;
|
||||
}
|
||||
|
||||
- (BOOL)isWebRTCEnabled
|
||||
{
|
||||
NSNumber *preference = [self tryGetValueForKey:PropertyListPreferencesKeyWebRTCEnabled];
|
||||
// Currently default to NO.
|
||||
return preference ? [preference boolValue] : NO;
|
||||
}
|
||||
|
||||
- (BOOL)getHasSentAMessage
|
||||
{
|
||||
NSNumber *preference = [self tryGetValueForKey:PropertyListPreferencesKeyHasSentAMessage];
|
||||
|
@ -127,10 +121,6 @@ NSString *const PropertyListPreferencesKeyWebRTCEnabled = @"WebRTCEnabled";
|
|||
[self setValueForKey:PropertyListPreferencesKeyScreenSecurity toValue:@(flag)];
|
||||
}
|
||||
|
||||
- (void)setIsWebRTCEnabled:(BOOL)flag
|
||||
{
|
||||
[self setValueForKey:PropertyListPreferencesKeyWebRTCEnabled toValue:@(flag)];
|
||||
}
|
||||
|
||||
- (void)setHasRegisteredVOIPPush:(BOOL)enabled
|
||||
{
|
||||
|
@ -179,6 +169,35 @@ NSString *const PropertyListPreferencesKeyWebRTCEnabled = @"WebRTCEnabled";
|
|||
return currentVersion;
|
||||
}
|
||||
|
||||
#pragma mark - Calling
|
||||
|
||||
#pragma mark WebRTC
|
||||
|
||||
- (BOOL)isWebRTCEnabled
|
||||
{
|
||||
NSNumber *preference = [self tryGetValueForKey:PropertyListPreferencesKeyWebRTCEnabled];
|
||||
// Currently default to NO.
|
||||
return preference ? [preference boolValue] : NO;
|
||||
}
|
||||
|
||||
- (void)setIsWebRTCEnabled:(BOOL)flag
|
||||
{
|
||||
[self setValueForKey:PropertyListPreferencesKeyWebRTCEnabled toValue:@(flag)];
|
||||
}
|
||||
|
||||
#pragma mark CallKit
|
||||
|
||||
- (BOOL)isCallKitEnabled
|
||||
{
|
||||
NSNumber *preference = [self tryGetValueForKey:PropertyListPreferencesKeyCallKitEnabled];
|
||||
return preference ? [preference boolValue] : YES;
|
||||
}
|
||||
|
||||
- (void)setIsCallKitEnabled:(BOOL)flag
|
||||
{
|
||||
[self setValueForKey:PropertyListPreferencesKeyCallKitEnabled toValue:@(flag)];
|
||||
}
|
||||
|
||||
#pragma mark Notification Preferences
|
||||
|
||||
- (BOOL)soundInForeground
|
||||
|
|
|
@ -17,18 +17,26 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@interface AdvancedSettingsTableViewController ()
|
||||
|
||||
@property NSArray *sectionsArray;
|
||||
|
||||
@property (nonatomic) UITableViewCell *enableWebRTCCell;
|
||||
@property (nonatomic) UITableViewCell *enableCallKitCell;
|
||||
@property (nonatomic) UITableViewCell *enableLogCell;
|
||||
@property (nonatomic) UITableViewCell *submitLogCell;
|
||||
@property (nonatomic) UITableViewCell *registerPushCell;
|
||||
|
||||
@property (nonatomic) UISwitch *enableWebRTCSwitch;
|
||||
@property (nonatomic) UISwitch *enableCallKitSwitch;
|
||||
@property (nonatomic) UISwitch *enableLogSwitch;
|
||||
@property (nonatomic, readonly) BOOL supportsCallKit;
|
||||
|
||||
@end
|
||||
|
||||
typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
|
||||
AdvancedSettingsTableViewControllerSectionLogging,
|
||||
AdvancedSettingsTableViewControllerSectionCalling,
|
||||
AdvancedSettingsTableViewControllerSectionPushNotifications,
|
||||
AdvancedSettingsTableViewControllerSection_Count // meta section
|
||||
};
|
||||
|
||||
@implementation AdvancedSettingsTableViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
|
@ -37,16 +45,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self.sectionsArray = @[
|
||||
NSLocalizedString(@"LOGGING_SECTION", nil),
|
||||
NSLocalizedString(@"PUSH_REGISTER_TITLE", @"Used in table section header and alert view title contexts")
|
||||
];
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [super initWithStyle:UITableViewStyleGrouped];
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
|
||||
self.title = NSLocalizedString(@"SETTINGS_ADVANCED_TITLE", @"");
|
||||
|
@ -62,6 +67,16 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
action:@selector(didToggleEnableWebRTCSwitch:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
self.enableWebRTCCell.accessoryView = self.enableWebRTCSwitch;
|
||||
|
||||
// CallKit opt-out
|
||||
self.enableCallKitCell = [UITableViewCell new];
|
||||
self.enableCallKitCell.textLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_CALLKIT_TITLE", @"Short table cell label");
|
||||
self.enableCallKitSwitch = [UISwitch new];
|
||||
[self.enableCallKitSwitch setOn:[[Environment getCurrent].preferences isCallKitEnabled]];
|
||||
[self.enableCallKitSwitch addTarget:self
|
||||
action:@selector(didToggleEnableCallKitSwitch:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
self.enableCallKitCell.accessoryView = self.enableCallKitSwitch;
|
||||
|
||||
// Enable Log
|
||||
self.enableLogCell = [[UITableViewCell alloc] init];
|
||||
|
@ -85,14 +100,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return (NSInteger)[self.sectionsArray count];
|
||||
return AdvancedSettingsTableViewControllerSection_Count;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return 1 + (self.enableLogSwitch.isOn ? 2 : 1);
|
||||
case 1:
|
||||
|
||||
AdvancedSettingsTableViewControllerSection settingsSection = (AdvancedSettingsTableViewControllerSection)section;
|
||||
switch (settingsSection) {
|
||||
case AdvancedSettingsTableViewControllerSectionLogging:
|
||||
return self.enableLogSwitch.isOn ? 2 : 1;
|
||||
case AdvancedSettingsTableViewControllerSectionCalling:
|
||||
return self.supportsCallKit ? 2 : 1;
|
||||
case AdvancedSettingsTableViewControllerSectionPushNotifications:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -101,26 +120,61 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
return [self.sectionsArray objectAtIndex:(NSUInteger)section];
|
||||
AdvancedSettingsTableViewControllerSection settingsSection = (AdvancedSettingsTableViewControllerSection)section;
|
||||
switch (settingsSection) {
|
||||
case AdvancedSettingsTableViewControllerSectionLogging:
|
||||
return NSLocalizedString(@"LOGGING_SECTION", nil);
|
||||
case AdvancedSettingsTableViewControllerSectionCalling:
|
||||
return NSLocalizedString(@"SETTINGS_SECTION_TITLE_CALLING", @"settings topic header for table section");
|
||||
case AdvancedSettingsTableViewControllerSectionPushNotifications:
|
||||
return NSLocalizedString(@"PUSH_REGISTER_TITLE", @"Used in table section header and alert view title contexts");
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.section == 0) {
|
||||
switch (indexPath.row) {
|
||||
case 0:
|
||||
return self.enableWebRTCCell;
|
||||
case 1:
|
||||
return self.enableLogCell;
|
||||
case 2:
|
||||
return self.enableLogSwitch.isOn ? self.submitLogCell : self.registerPushCell;
|
||||
}
|
||||
} else {
|
||||
return self.registerPushCell;
|
||||
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
|
||||
{
|
||||
AdvancedSettingsTableViewControllerSection settingsSection = (AdvancedSettingsTableViewControllerSection)section;
|
||||
switch (settingsSection) {
|
||||
case AdvancedSettingsTableViewControllerSectionCalling:
|
||||
return NSLocalizedString(@"SETTINGS_SECTION_CALL_KIT_DESCRIPTION", @"Settings table section footer.");
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
NSAssert(false, @"No Cell configured");
|
||||
|
||||
return nil;
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
AdvancedSettingsTableViewControllerSection settingsSection = (AdvancedSettingsTableViewControllerSection)indexPath.section;
|
||||
switch (settingsSection) {
|
||||
case AdvancedSettingsTableViewControllerSectionLogging:
|
||||
switch (indexPath.row) {
|
||||
case 0:
|
||||
return self.enableLogCell;
|
||||
case 1:
|
||||
OWSAssert(self.enableLogSwitch.isOn);
|
||||
return self.submitLogCell;
|
||||
}
|
||||
case AdvancedSettingsTableViewControllerSectionCalling:
|
||||
switch (indexPath.row) {
|
||||
case 0:
|
||||
return self.enableWebRTCCell;
|
||||
case 1:
|
||||
OWSAssert(self.supportsCallKit);
|
||||
return self.enableCallKitCell;
|
||||
default:
|
||||
// Unknown cell
|
||||
OWSAssert(NO);
|
||||
return nil;
|
||||
}
|
||||
case AdvancedSettingsTableViewControllerSectionPushNotifications:
|
||||
return self.registerPushCell;
|
||||
default:
|
||||
// Unknown section
|
||||
OWSAssert(NO);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
@ -207,6 +261,19 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)didToggleEnableCallKitSwitch:(UISwitch *)sender {
|
||||
DDLogInfo(@"%@ user toggled call kit preference: %@", self.tag, (sender.isOn ? @"ON" : @"OFF"));
|
||||
[[Environment getCurrent].preferences setIsCallKitEnabled:sender.isOn];
|
||||
[[Environment getCurrent].callService createCallUIAdapter];
|
||||
}
|
||||
|
||||
#pragma mark - Util
|
||||
|
||||
- (BOOL)supportsCallKit
|
||||
{
|
||||
return SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(10, 0);
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)tag
|
||||
|
|
|
@ -717,6 +717,9 @@
|
|||
/* Navbar title */
|
||||
"SETTINGS_ABOUT" = "About";
|
||||
|
||||
/* Short table cell label */
|
||||
"SETTINGS_ADVANCED_CALLKIT_TITLE" = "Use CallKit";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"SETTINGS_ADVANCED_DEBUGLOG" = "Enable Debug Log";
|
||||
|
||||
|
@ -727,7 +730,7 @@
|
|||
"SETTINGS_ADVANCED_TITLE" = "Advanced";
|
||||
|
||||
/* This setting is used to switch between new-style WebRTC calling and old-style RedPhone calling. */
|
||||
"SETTINGS_ADVANCED_WEBRTC" = "Enable WebRTC Calling";
|
||||
"SETTINGS_ADVANCED_WEBRTC" = "Enable Video Calling (Beta)";
|
||||
|
||||
/* The message of the alert shown when updates to the WebRTC property fail. */
|
||||
"SETTINGS_ADVANCED_WEBRTC_FAILED_MESSAGE" = "Could not update your preferences.";
|
||||
|
@ -789,6 +792,12 @@
|
|||
/* No comment provided by engineer. */
|
||||
"SETTINGS_SCREEN_SECURITY_DETAIL" = "Prevents Signal previews from appearing in the app switcher.";
|
||||
|
||||
/* Settings table section footer. */
|
||||
"SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "CallKit allows you to answer calls directly from your lockscreen. Be aware that when using CallKit, Apple syncs some call metadata to your iCloud account.";
|
||||
|
||||
/* settings topic header for table section */
|
||||
"SETTINGS_SECTION_TITLE_CALLING" = "Calling";
|
||||
|
||||
/* Section header */
|
||||
"SETTINGS_SECURITY_TITLE" = "Screen Security";
|
||||
|
||||
|
|
Loading…
Reference in a new issue