Skip to content

Commit

Permalink
- #151 CallKit: Support initiating outgoing phone calls
Browse files Browse the repository at this point in the history
  • Loading branch information
khaliddd committed Nov 2, 2021
1 parent 0e4cee2 commit a216da1
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 21 deletions.
31 changes: 14 additions & 17 deletions Snikket - Share/Base.lproj/MainInterface.storyboard
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Share View Controller-->
<scene sceneID="ceB-am-kn3">
<objects>
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModule="Tigase_Messenger___Share" customModuleProvider="target" sceneMemberID="viewController">
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModule="Snikket___Share" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="8bI-gs-bmD"/>
<viewControllerLayoutGuide type="bottom" id="d5i-Ba-RvD"/>
Expand All @@ -32,21 +29,21 @@
<!--Accounts-->
<scene sceneID="taW-D3-3Yx">
<objects>
<tableViewController storyboardIdentifier="accountSelectionViewController" title="Accounts" useStoryboardIdentifierAsRestorationIdentifier="YES" id="6l2-wd-vXh" customClass="AccountsTableViewController" customModule="Tigase_Messenger___Share" customModuleProvider="target" sceneMemberID="viewController">
<tableViewController storyboardIdentifier="accountSelectionViewController" title="Accounts" useStoryboardIdentifierAsRestorationIdentifier="YES" id="6l2-wd-vXh" customClass="AccountsTableViewController" customModule="Snikket___Share" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="977-Qx-KPe">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="accountTableViewCell" selectionStyle="default" indentationWidth="10" reuseIdentifier="accountTableViewCell" id="SZs-Vf-W54" customClass="AccountTableViewCell" customModule="Tigase_Messenger___Share" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="accountTableViewCell" selectionStyle="default" indentationWidth="10" reuseIdentifier="accountTableViewCell" id="SZs-Vf-W54" customClass="AccountTableViewCell" customModule="Snikket___Share" customModuleProvider="target">
<rect key="frame" x="0.0" y="44.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="SZs-Vf-W54" id="iwn-zZ-n1r">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="95D-JK-fLM">
<rect key="frame" x="8" y="8" width="359" height="27.5"/>
<rect key="frame" x="16" y="11" width="343" height="22"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
Expand Down Expand Up @@ -78,21 +75,21 @@
<!--Recipients-->
<scene sceneID="bWt-BT-C6m">
<objects>
<tableViewController storyboardIdentifier="recipientsSelectionViewController" title="Recipients" useStoryboardIdentifierAsRestorationIdentifier="YES" id="wpy-g7-270" customClass="RecipientsSelectionViewController" customModule="Tigase_Messenger___Share" customModuleProvider="target" sceneMemberID="viewController">
<tableViewController storyboardIdentifier="recipientsSelectionViewController" title="Recipients" useStoryboardIdentifierAsRestorationIdentifier="YES" id="wpy-g7-270" customClass="RecipientsSelectionViewController" customModule="Snikket___Share" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="SH7-od-nvj">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="accountTableViewCell" selectionStyle="default" indentationWidth="10" reuseIdentifier="recipientTableViewCell" id="lwl-dC-64B" customClass="RecipientTableViewCell" customModule="Tigase_Messenger___Share" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" restorationIdentifier="accountTableViewCell" selectionStyle="default" indentationWidth="10" reuseIdentifier="recipientTableViewCell" id="lwl-dC-64B" customClass="RecipientTableViewCell" customModule="Snikket___Share" customModuleProvider="target">
<rect key="frame" x="0.0" y="44.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="lwl-dC-64B" id="0s3-Da-XsL">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Geq-xy-Tr2">
<rect key="frame" x="8" y="8" width="359" height="27.5"/>
<rect key="frame" x="16" y="11" width="343" height="22"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
Expand Down
8 changes: 8 additions & 0 deletions Snikket.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
37359BDF2731427500066DC1 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37359BDE2731427500066DC1 /* Intents.framework */; };
373A8020271063E1000E50FE /* TelephonyProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373A801F271063E1000E50FE /* TelephonyProviderViewController.swift */; };
374AB4C3273153E700E16682 /* CallsAccountSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374AB4C2273153E700E16682 /* CallsAccountSelectionController.swift */; };
3759635F26F72F1900831F4C /* Welcome.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3759636126F72F1900831F4C /* Welcome.storyboard */; };
3759636A26F72FD700831F4C /* Groupchat.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3759636C26F72FD700831F4C /* Groupchat.storyboard */; };
3759637126F7303100831F4C /* VoIP.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3759637326F7303100831F4C /* VoIP.storyboard */; };
Expand Down Expand Up @@ -305,7 +307,9 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
37359BDE2731427500066DC1 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; };
373A801F271063E1000E50FE /* TelephonyProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelephonyProviderViewController.swift; sourceTree = "<group>"; };
374AB4C2273153E700E16682 /* CallsAccountSelectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallsAccountSelectionController.swift; sourceTree = "<group>"; };
3759635C26F72EAA00831F4C /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/LaunchScreen.strings; sourceTree = "<group>"; };
3759635D26F72ED700831F4C /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Main.strings; sourceTree = "<group>"; };
3759635E26F72ED700831F4C /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/MainInterface.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -642,6 +646,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
37359BDF2731427500066DC1 /* Intents.framework in Frameworks */,
FE1A34A7258CD3EE0058B86A /* WebRTC.xcframework in Frameworks */,
FE5079F01CD3CA91001A015C /* Security.framework in Frameworks */,
3797D5C026EA456F0091DAF8 /* HSLuvSwift in Frameworks */,
Expand All @@ -664,6 +669,7 @@
FE1908902584D69400CA049F /* Frameworks */ = {
isa = PBXGroup;
children = (
37359BDE2731427500066DC1 /* Intents.framework */,
FE1A349F258CD3E10058B86A /* WebRTC.xcframework */,
FE1908962584D69400CA049F /* OpenSSL.xcframework */,
);
Expand All @@ -680,6 +686,7 @@
FE2D481924505F1600C13CE5 /* CallManager.swift */,
FE2D481B24518C2800C13CE5 /* RTCCameraVideoCapturer_Format.swift */,
FE1A07472525EDD4004F38A0 /* ExternalServiceDiscovery_Service_extension.swift */,
374AB4C2273153E700E16682 /* CallsAccountSelectionController.swift */,
);
path = voip;
sourceTree = "<group>";
Expand Down Expand Up @@ -1515,6 +1522,7 @@
FE2D481C24518C2800C13CE5 /* RTCCameraVideoCapturer_Format.swift in Sources */,
FE4071E421E2605900F09B58 /* VideoCallController.swift in Sources */,
FE9E13731F260B33005C0EE5 /* StepperTableViewCell.swift in Sources */,
374AB4C3273153E700E16682 /* CallsAccountSelectionController.swift in Sources */,
FE6545601E9E7B85006A14AC /* RegisterAccountController.swift in Sources */,
FE507A181CDB7B3B001A015C /* ChatViewController.swift in Sources */,
FEFB63AD1F31E4EE00EFB3E7 /* MainTabBarController.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Snikket.xcodeproj/xcshareddata/xcschemes/Snikket.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
Expand Down
83 changes: 83 additions & 0 deletions Snikket/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import TigaseSwift
import Shared
import WebRTC
import BackgroundTasks
import Intents

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
Expand Down Expand Up @@ -769,6 +770,88 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
case register
}
}
}

// Making Call From System Calls App
extension AppDelegate {
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

let interaction = userActivity.interaction
if let startAudioCallIntent = interaction?.intent as? INStartAudioCallIntent {

let contact = startAudioCallIntent.contacts?.first

let contactHandle = contact?.personHandle

if let callTo = contactHandle?.value {
if contactHandle?.type == .phoneNumber {
// call from telephony configured account
getTelephonyConfiguredAccounts(completion: { [callTo] account, provider in
self.makeOutgoingCall(account: account, callTo: callTo + "@" + provider, type: .phoneNumber)
})
} else {
// show account selection to make call
showAccountSelection(accounts: AccountManager.getActiveAccounts()) { [callTo] account in
self.makeOutgoingCall(account: account, callTo: callTo, type: .unknown)
}
}
}
}
return true
}

func getTelephonyConfiguredAccounts(completion: @escaping (BareJID,String) -> Void) {
var telephonyAccounts = [BareJID:String]()
let accounts = AccountManager.getActiveAccounts()
for account in accounts {
if let provider = AccountSettings.telephonyProvider(account).getString() {
telephonyAccounts[account] = provider
}
}
if telephonyAccounts.isEmpty {
// show alert
showNoProviderConfigured()
} else if telephonyAccounts.count == 1, let first = telephonyAccounts.first {
completion(first.key,first.value)
} else {
// show account selection sheet
showAccountSelection(accounts: Array(telephonyAccounts.keys), completion: { selectedAccount in
completion(selectedAccount ,telephonyAccounts[selectedAccount] ?? "")
})
}
}

func showNoProviderConfigured() {
let alert : UIAlertController = UIAlertController(title: NSLocalizedString("No Telephony Provider!", comment: ""), message: NSLocalizedString("Please Select a Telephony Provider from Settings", comment: ""), preferredStyle: .alert)
let ok = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .cancel, handler: nil)
alert.addAction(ok)
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
}

func showAccountSelection(accounts: [BareJID], completion: @escaping (BareJID) -> Void) {
let alert : UIAlertController = UIAlertController(title: NSLocalizedString("Select Account for Call", comment: ""), message: nil, preferredStyle: .alert)
alert.view.backgroundColor = .black
alert.view.layer.cornerRadius = 8.0
let contactNumVC = CallsAccountSelectionController()
contactNumVC.accounts = accounts
contactNumVC.preferredContentSize = CGSize(width: alert.view.frame.width, height: (50.0 * CGFloat(accounts.count)))
alert.setValue(contactNumVC, forKeyPath: "contentViewController")
let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
alert.addAction(cancel)

contactNumVC.didSelectAccount = { account in
print(account)
completion(account)
}

self.window?.rootViewController?.present(alert, animated: true, completion: nil)
}

func makeOutgoingCall(account: BareJID, callTo: String, type: INPersonHandleType) {
guard let rootVC = self.window?.rootViewController else { return }
let jid = BareJID(callTo)
VideoCallController.call(jid: jid, from: account, media: [.audio], sender: rootVC)
}
}


Loading

0 comments on commit a216da1

Please sign in to comment.