mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 21:39:12 +00:00
Show ElementCalls in the system Recents list and allow deep linking back into a call from there
This commit is contained in:
parent
16fc7caa62
commit
f6c476eeca
@ -17,6 +17,7 @@
|
|||||||
import AnalyticsEvents
|
import AnalyticsEvents
|
||||||
import BackgroundTasks
|
import BackgroundTasks
|
||||||
import Combine
|
import Combine
|
||||||
|
import Intents
|
||||||
import MatrixRustSDK
|
import MatrixRustSDK
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Version
|
import Version
|
||||||
@ -236,6 +237,20 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleUserActivity(_ userActivity: NSUserActivity) {
|
||||||
|
// `INStartVideoCallIntent` is to be replaced with `INStartCallIntent`
|
||||||
|
// but calls from Recents still send it ¯\_(ツ)_/¯
|
||||||
|
guard let intent = userActivity.interaction?.intent as? INStartVideoCallIntent,
|
||||||
|
let contact = intent.contacts?.first,
|
||||||
|
let roomIdentifier = contact.personHandle?.value else {
|
||||||
|
MXLog.error("Failed retrieving information from userActivity: \(userActivity)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
MXLog.info("Starting call in room: \(roomIdentifier)")
|
||||||
|
handleAppRoute(AppRoute.call(roomID: roomIdentifier))
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - AuthenticationFlowCoordinatorDelegate
|
// MARK: - AuthenticationFlowCoordinatorDelegate
|
||||||
|
|
||||||
func authenticationFlowCoordinator(didLoginWithSession userSession: UserSessionProtocol) {
|
func authenticationFlowCoordinator(didLoginWithSession userSession: UserSessionProtocol) {
|
||||||
|
@ -18,5 +18,8 @@ import Foundation
|
|||||||
|
|
||||||
protocol AppCoordinatorProtocol: CoordinatorProtocol {
|
protocol AppCoordinatorProtocol: CoordinatorProtocol {
|
||||||
var windowManager: SecureWindowManagerProtocol { get }
|
var windowManager: SecureWindowManagerProtocol { get }
|
||||||
|
|
||||||
@discardableResult func handleDeepLink(_ url: URL, isExternalURL: Bool) -> Bool
|
@discardableResult func handleDeepLink(_ url: URL, isExternalURL: Bool) -> Bool
|
||||||
|
|
||||||
|
func handleUserActivity(_ userActivity: NSUserActivity)
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,11 @@ struct Application: App {
|
|||||||
openURLInSystemBrowser($0)
|
openURLInSystemBrowser($0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onContinueUserActivity("INStartVideoCallIntent", perform: { userActivity in
|
||||||
|
// `INStartVideoCallIntent` is to be replaced with `INStartCallIntent`
|
||||||
|
// but calls from Recents still send it ¯\_(ツ)_/¯
|
||||||
|
appCoordinator.handleUserActivity(userActivity)
|
||||||
|
})
|
||||||
.task {
|
.task {
|
||||||
appCoordinator.start()
|
appCoordinator.start()
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
|
|||||||
|
|
||||||
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
|
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
|
||||||
guard let roomID = payload.dictionaryPayload[ElementCallServiceNotificationKey.roomID.rawValue] as? String else {
|
guard let roomID = payload.dictionaryPayload[ElementCallServiceNotificationKey.roomID.rawValue] as? String else {
|
||||||
MXLog.error("Somethnig went wrong, missing room identifier for incoming voip call: \(payload)")
|
MXLog.error("Something went wrong, missing room identifier for incoming voip call: \(payload)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,20 +102,18 @@ class ElementCallService: NSObject, ElementCallServiceProtocol, PKPushRegistryDe
|
|||||||
|
|
||||||
let configuration = CXProviderConfiguration()
|
let configuration = CXProviderConfiguration()
|
||||||
configuration.supportsVideo = true
|
configuration.supportsVideo = true
|
||||||
configuration.includesCallsInRecents = false
|
configuration.includesCallsInRecents = true
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/46077628/730924
|
||||||
|
configuration.supportedHandleTypes = [.generic]
|
||||||
|
|
||||||
let update = CXCallUpdate()
|
let update = CXCallUpdate()
|
||||||
update.hasVideo = true
|
update.hasVideo = true
|
||||||
|
|
||||||
update.localizedCallerName = payload.dictionaryPayload[ElementCallServiceNotificationKey.roomDisplayName.rawValue] as? String
|
update.localizedCallerName = payload.dictionaryPayload[ElementCallServiceNotificationKey.roomDisplayName.rawValue] as? String
|
||||||
|
|
||||||
if let senderDisplayName = payload.dictionaryPayload[ElementCallServiceNotificationKey.senderDisplayName.rawValue] as? String {
|
// https://stackoverflow.com/a/41230020/730924
|
||||||
update.remoteHandle = .init(type: .generic, value: senderDisplayName)
|
update.remoteHandle = .init(type: .generic, value: roomID)
|
||||||
} else if let senderID = payload.dictionaryPayload[ElementCallServiceNotificationKey.senderID.rawValue] as? String {
|
|
||||||
update.remoteHandle = .init(type: .generic, value: senderID)
|
|
||||||
} else {
|
|
||||||
MXLog.error("Something went wrong, both the user display name and ID are nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
let callProvider = CXProvider(configuration: configuration)
|
let callProvider = CXProvider(configuration: configuration)
|
||||||
callProvider.setDelegate(self, queue: nil)
|
callProvider.setDelegate(self, queue: nil)
|
||||||
|
@ -24,8 +24,6 @@ enum ElementCallServiceAction {
|
|||||||
enum ElementCallServiceNotificationKey: String {
|
enum ElementCallServiceNotificationKey: String {
|
||||||
case roomID
|
case roomID
|
||||||
case roomDisplayName
|
case roomDisplayName
|
||||||
case senderID
|
|
||||||
case senderDisplayName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ElementCallServiceNotificationDiscardDelta = 10.0
|
let ElementCallServiceNotificationDiscardDelta = 10.0
|
||||||
|
@ -70,6 +70,10 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, SecureWindowManagerDelegate
|
|||||||
fatalError("Not implemented.")
|
fatalError("Not implemented.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleUserActivity(_ activity: NSUserActivity) {
|
||||||
|
fatalError("Not implemented.")
|
||||||
|
}
|
||||||
|
|
||||||
func windowManagerDidConfigureWindows(_ windowManager: SecureWindowManagerProtocol) {
|
func windowManagerDidConfigureWindows(_ windowManager: SecureWindowManagerProtocol) {
|
||||||
ServiceLocator.shared.userIndicatorController.window = windowManager.overlayWindow
|
ServiceLocator.shared.userIndicatorController.window = windowManager.overlayWindow
|
||||||
|
|
||||||
|
@ -41,4 +41,8 @@ class UnitTestsAppCoordinator: AppCoordinatorProtocol {
|
|||||||
func handleDeepLink(_ url: URL, isExternalURL: Bool) -> Bool {
|
func handleDeepLink(_ url: URL, isExternalURL: Bool) -> Bool {
|
||||||
fatalError("Not implemented.")
|
fatalError("Not implemented.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleUserActivity(_ activity: NSUserActivity) {
|
||||||
|
fatalError("Not implemented.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
<key>NSUserActivityTypes</key>
|
<key>NSUserActivityTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>INSendMessageIntent</string>
|
<string>INSendMessageIntent</string>
|
||||||
|
<string>INStartCallIntent</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
|
@ -82,7 +82,8 @@ targets:
|
|||||||
productionAppName: $(PRODUCTION_APP_NAME)
|
productionAppName: $(PRODUCTION_APP_NAME)
|
||||||
ITSAppUsesNonExemptEncryption: false
|
ITSAppUsesNonExemptEncryption: false
|
||||||
NSUserActivityTypes: [
|
NSUserActivityTypes: [
|
||||||
INSendMessageIntent
|
INSendMessageIntent,
|
||||||
|
INStartCallIntent,
|
||||||
]
|
]
|
||||||
NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera.
|
NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera.
|
||||||
NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone.
|
NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone.
|
||||||
|
@ -206,12 +206,8 @@ class NotificationServiceExtension: UNNotificationServiceExtension {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var payload = [ElementCallServiceNotificationKey.roomID.rawValue: itemProxy.roomID,
|
let payload = [ElementCallServiceNotificationKey.roomID.rawValue: itemProxy.roomID,
|
||||||
ElementCallServiceNotificationKey.roomDisplayName.rawValue: itemProxy.roomDisplayName,
|
ElementCallServiceNotificationKey.roomDisplayName.rawValue: itemProxy.roomDisplayName]
|
||||||
ElementCallServiceNotificationKey.senderID.rawValue: itemProxy.senderID]
|
|
||||||
if let senderDisplayName = itemProxy.senderDisplayName {
|
|
||||||
payload[ElementCallServiceNotificationKey.senderDisplayName.rawValue] = senderDisplayName
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await CXProvider.reportNewIncomingVoIPPushPayload(payload)
|
try await CXProvider.reportNewIncomingVoIPPushPayload(payload)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user