Skip to content

Commit

Permalink
Add hasVideo parameter on startCall
Browse files Browse the repository at this point in the history
  • Loading branch information
ipavlidakis committed Jan 24, 2025
1 parent dac33b1 commit 6449132
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 42 deletions.
8 changes: 6 additions & 2 deletions Sources/StreamVideo/Call.swift
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
/// - maxDuration: An optional integer representing the maximum duration of the call in seconds.
/// - maxParticipants: An optional integer representing the maximum number of participants allowed in the call.
/// - backstage: An optional backstage request.
/// - hasVideo: A boolean indicating if the call will be video or only audio. Still requires appropriate
/// setting of ``CallSettings`.`
/// - Returns: A `CallResponse` object representing the created call.
/// - Throws: An error if the call creation fails.
@discardableResult
Expand All @@ -238,7 +240,8 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
notify: Bool = false,
maxDuration: Int? = nil,
maxParticipants: Int? = nil,
backstage: BackstageSettingsRequest? = nil
backstage: BackstageSettingsRequest? = nil,
hasVideo: Bool? = nil
) async throws -> CallResponse {
var membersRequest = [MemberRequest]()
memberIds?.forEach {
Expand Down Expand Up @@ -268,7 +271,8 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
members: membersRequest,
settingsOverride: settingsOverride,
startsAt: startsAt,
team: team
team: team,
video: hasVideo
),
notify: notify,
ring: ring
Expand Down
10 changes: 4 additions & 6 deletions Sources/StreamVideo/CallKit/CallKitPushNotificationAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
var cid: String
var localizedCallerName: String
var callerId: String
var hasVideo: Bool
var hasVideo: Bool?

public init(
cid: String,
localizedCallerName: String,
callerId: String,
hasVideo: Bool
hasVideo: Bool? = nil
) {
self.cid = cid
self.localizedCallerName = localizedCallerName
Expand Down Expand Up @@ -107,7 +107,6 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
"Received VoIP push notification with cid:\(content.cid) callerId:\(content.callerId) callerName:\(content.localizedCallerName)."
)

callKitService.supportsVideo = content.hasVideo
callKitService.reportIncomingCall(
content.cid,
localizedCallerName: content.localizedCallerName,
Expand Down Expand Up @@ -136,8 +135,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
return .init(
cid: "unknown",
localizedCallerName: defaultCallText,
callerId: defaultCallText,
hasVideo: false
callerId: defaultCallText
)
}

Expand All @@ -155,7 +153,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
fallback: defaultCallText
)

let hasVideo = streamDict[PayloadKey.video.rawValue] as? Bool ?? false
let hasVideo = streamDict[PayloadKey.video.rawValue] as? Bool

return .init(
cid: cid,
Expand Down
29 changes: 4 additions & 25 deletions Sources/StreamVideo/CallKit/CallKitService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,39 +109,17 @@ open class CallKitService: NSObject, CXProviderDelegate, @unchecked Sendable {
/// - cid: The call ID.
/// - localizedCallerName: The localized caller name.
/// - callerId: The caller's identifier.
/// - hasVideo: Indicator if call is video or audio. If nil we default to the value of `supportsVideo`
/// - completion: A closure to be called upon completion.
@MainActor
open func reportIncomingCall(
_ cid: String,
localizedCallerName: String,
callerId: String,
hasVideo: Bool? = nil,
completion: @escaping (Error?) -> Void
) {
reportIncomingCall(
cid,
localizedCallerName: localizedCallerName,
callerId: callerId,
hasVideo: false,
completion: completion
)
}

/// Reports an incoming call to the CallKit framework.
///
/// - Parameters:
/// - cid: The call ID.
/// - localizedCallerName: The localized caller name.
/// - callerId: The caller's identifier.
/// - hasVideo: Indicator if call is video or audio.
/// - completion: A closure to be called upon completion.
@MainActor
open func reportIncomingCall(
_ cid: String,
localizedCallerName: String,
callerId: String,
hasVideo: Bool,
completion: @escaping (Error?) -> Void
) {
let hasVideo = hasVideo ?? supportsVideo
let (callUUID, callUpdate) = buildCallUpdate(
cid: cid,
localizedCallerName: localizedCallerName,
Expand All @@ -162,6 +140,7 @@ open class CallKitService: NSObject, CXProviderDelegate, @unchecked Sendable {
cid:\(cid)
callerId:\(callerId)
callerName:\(localizedCallerName)
hasVideo: \(hasVideo)
"""
)

Expand Down
8 changes: 6 additions & 2 deletions Sources/StreamVideoSwiftUI/CallViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ open class CallViewModel: ObservableObject {
/// - maxParticipants: An optional integer representing the maximum number of participants allowed in the call.
/// - startsAt: An optional date when the call starts.
/// - backstage: An optional request for setting up backstage.
/// - hasVideo: A boolean indicating if the call will be video or only audio. Still requires appropriate
/// setting of ``CallSettings`.`
public func startCall(
callType: String,
callId: String,
Expand All @@ -337,7 +339,8 @@ open class CallViewModel: ObservableObject {
maxParticipants: Int? = nil,
startsAt: Date? = nil,
backstage: BackstageSettingsRequest? = nil,
customData: [String: RawJSON]? = nil
customData: [String: RawJSON]? = nil,
hasVideo: Bool? = nil
) {
outgoingCallMembers = members
callingState = ring ? .outgoing : .joining
Expand Down Expand Up @@ -368,7 +371,8 @@ open class CallViewModel: ObservableObject {
custom: customData,
ring: ring,
maxDuration: maxDuration,
maxParticipants: maxParticipants
maxParticipants: maxParticipants,
hasVideo: hasVideo
)
let timeoutSeconds = TimeInterval(
callData.settings.ring.autoCancelTimeoutMs / 1000
Expand Down
24 changes: 21 additions & 3 deletions StreamVideoTests/CallKit/CallKitPushNotificationAdapterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ final class CallKitPushNotificationAdapterTests: XCTestCase {
)
}

@MainActor
func test_pushRegistryDidReceiveIncomingPush_typeIsVoIP_hasVideoIsNil_reportIncomingCallWasCalledAsExpected() {
assertDidReceivePushNotification(
.init(
cid: "123",
localizedCallerName: "TestUser",
callerId: "test_user",
hasVideo: nil
)
)
}

@MainActor
func test_pushRegistryDidReceiveIncomingPush_typeIsVoIPWithDisplayNameAndCallerName_reportIncomingCallWasCalledAsExpected() {
assertDidReceivePushNotification(
Expand Down Expand Up @@ -134,16 +146,22 @@ final class CallKitPushNotificationAdapterTests: XCTestCase {
) {
let pushPayload = MockPKPushPayload()
pushPayload.stubType = contentType
pushPayload.stubDictionaryPayload = content.map { [
var payload: [String: Any] = content.map { [
"stream": [
"call_cid": $0.cid,
"call_display_name": displayName,
"created_by_display_name": $0.localizedCallerName,
"created_by_id": $0.callerId,
"video": $0.hasVideo
"created_by_id": $0.callerId
]
] } ?? [:]

if let hasVideo = content?.hasVideo, var streamPayload = payload["stream"] as? [String: Any] {
streamPayload["video"] = hasVideo
payload["stream"] = streamPayload
}

pushPayload.stubDictionaryPayload = payload

let completionWasCalledExpectation = expectation(description: "Completion was called.")
completionWasCalledExpectation.isInverted = content == nil
subject.pushRegistry(
Expand Down
44 changes: 42 additions & 2 deletions StreamVideoTests/CallKit/CallKitServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ final class CallKitServiceTests: XCTestCase, @unchecked Sendable {
// MARK: - reportIncomingCall

@MainActor
func test_reportIncomingCall_hasVideo_callUpdateWasConfiguredCorrectly() throws {
func test_reportIncomingCall_hasVideoTrue_callUpdateWasConfiguredCorrectly() throws {
subject.reportIncomingCall(
cid,
localizedCallerName: localizedCallerName,
Expand All @@ -76,7 +76,7 @@ final class CallKitServiceTests: XCTestCase, @unchecked Sendable {
}

@MainActor
func test_reportIncomingCall_doesNotSupportVideo_callUpdateWasConfiguredCorrectly() throws {
func test_reportIncomingCall_hasVideoFalse_callUpdateWasConfiguredCorrectly() throws {
subject.reportIncomingCall(
cid,
localizedCallerName: localizedCallerName,
Expand All @@ -94,6 +94,46 @@ final class CallKitServiceTests: XCTestCase, @unchecked Sendable {
}
}

@MainActor
func test_reportIncomingCall_hasVideoNilSupportsVideoTrue_callUpdateWasConfiguredCorrectly() throws {
subject.supportsVideo = true
subject.reportIncomingCall(
cid,
localizedCallerName: localizedCallerName,
callerId: callerId,
hasVideo: nil
) { _ in }

let invocation = try XCTUnwrap(callProvider.invocations.first)

switch invocation {
case let .reportNewIncomingCall(_, update, _):
XCTAssertTrue(update.hasVideo)
default:
XCTFail()
}
}

@MainActor
func test_reportIncomingCall_hasVideoNilSupportsVideoFalse_callUpdateWasConfiguredCorrectly() throws {
subject.supportsVideo = false
subject.reportIncomingCall(
cid,
localizedCallerName: localizedCallerName,
callerId: callerId,
hasVideo: nil
) { _ in }

let invocation = try XCTUnwrap(callProvider.invocations.first)

switch invocation {
case let .reportNewIncomingCall(_, update, _):
XCTAssertFalse(update.hasVideo)
default:
XCTFail()
}
}

@MainActor
func test_reportIncomingCall_withIconTemplateImageData_callUpdateWasConfiguredCorrectly() throws {
subject = .init()
Expand Down
4 changes: 2 additions & 2 deletions StreamVideoTests/Utilities/Mocks/MockCallKitService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class MockCallKitService: CallKitService {
cid: String,
callerName: String,
callerId: String,
hasVideo: Bool,
hasVideo: Bool?,
completion: (Error?) -> Void
)?

Expand All @@ -20,7 +20,7 @@ final class MockCallKitService: CallKitService {
_ cid: String,
localizedCallerName: String,
callerId: String,
hasVideo: Bool,
hasVideo: Bool?,
completion: @escaping ((any Error)?) -> Void
) {
reportIncomingCallWasCalled = (cid, localizedCallerName, callerId, hasVideo, completion)
Expand Down

0 comments on commit 6449132

Please sign in to comment.