Skip to content

1.21.0 Release #767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Apr 22, 2025
Merged

1.21.0 Release #767

merged 19 commits into from
Apr 22, 2025

Conversation

Stream-SDK-Bot
Copy link
Collaborator

✅ Added

  • Countdown timer and waiting participants info to the livestream player #754
  • EventPublisher for Call objects. #759
  • You can now access the custom-data attached on a Call object you received as incoming. #766

🔄 Changed

  • CallViewModel.callingState transition to .idle just before moving to .inCall after the user has accepted the call. #759
  • AudioSession mode wasn't configured correctly for audio-only calls. #762
  • Updated WebRTC version to 125.6422.070 #760
  • Picture-in-Picture improved UI and stability fixes. #724

🐞 Fixed

  • Sound resources weren't loaded correctly when the SDK was linked via SPM. #757
  • Redefined the priorities by which dashboard audio settings will be applied. #758

@Stream-SDK-Bot Stream-SDK-Bot requested a review from a team as a code owner April 22, 2025 14:42
Copy link

Public Interface

+ public enum InternetConnectionStatus: Equatable, Sendable  
+ 
+   case unknown
+   case available(InternetConnectionQuality)
+   case unavailable

+ public protocol InternetConnectionProtocol

+ public enum InternetConnectionQuality: Equatable, Sendable  
+ 
+   case great
+   case expensive
+   case constrained

+ public struct Resource: ExpressibleByStringLiteral  
+ 
+   public var name: String
+   public var `extension`: String?
+   public var fileName: String
+   
+ 
+   public init(name: String,extension: String? = nil)
+   public init(stringLiteral value: StringLiteralType)

+ extension InternetConnectionStatus  
+ 
+   public var isAvailable: Bool

+ extension InternetConnection: InjectionKey  
+ 
+   nonisolated public static var currentValue: InternetConnectionProtocol

- extension CallSettingsResponse  
- 
-   public var toCallSettings: CallSettings

 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public let microphone: MicrophoneManager
+   public var eventPublisher: AnyPublisher<VideoEvent, Never>
-   public let camera: CameraManager
+   public let microphone: MicrophoneManager
-   public let speaker: SpeakerManager
+   public let camera: CameraManager
-   
+   public let speaker: SpeakerManager
- 
+   
-   @discardableResult public func join(create: Bool = false,options: CreateCallOptions? = nil,ring: Bool = false,notify: Bool = false,callSettings: CallSettings? = nil)async throws -> JoinCallResponse
+ 
-   public func get(membersLimit: Int? = nil,ring: Bool = false,notify: Bool = false)async throws -> GetCallResponse
+   @discardableResult public func join(create: Bool = false,options: CreateCallOptions? = nil,ring: Bool = false,notify: Bool = false,callSettings: CallSettings? = nil)async throws -> JoinCallResponse
-   @discardableResult public func ring()async throws -> CallResponse
+   public func get(membersLimit: Int? = nil,ring: Bool = false,notify: Bool = false)async throws -> GetCallResponse
-   @discardableResult public func notify()async throws -> CallResponse
+   @discardableResult public func ring()async throws -> CallResponse
-   @discardableResult public func create(members: [MemberRequest]? = nil,memberIds: [String]? = nil,custom: [String: RawJSON]? = nil,startsAt: Date? = nil,team: String? = nil,ring: Bool = false,notify: Bool = false,maxDuration: Int? = nil,maxParticipants: Int? = nil,backstage: BackstageSettingsRequest? = nil,video: Bool? = nil,transcription: TranscriptionSettingsRequest? = nil)async throws -> CallResponse
+   @discardableResult public func notify()async throws -> CallResponse
-   @discardableResult public func update(custom: [String: RawJSON]? = nil,settingsOverride: CallSettingsRequest? = nil,startsAt: Date? = nil)async throws -> UpdateCallResponse
+   @discardableResult public func create(members: [MemberRequest]? = nil,memberIds: [String]? = nil,custom: [String: RawJSON]? = nil,startsAt: Date? = nil,team: String? = nil,ring: Bool = false,notify: Bool = false,maxDuration: Int? = nil,maxParticipants: Int? = nil,backstage: BackstageSettingsRequest? = nil,video: Bool? = nil,transcription: TranscriptionSettingsRequest? = nil)async throws -> CallResponse
-   @discardableResult public func accept()async throws -> AcceptCallResponse
+   @discardableResult public func update(custom: [String: RawJSON]? = nil,settingsOverride: CallSettingsRequest? = nil,startsAt: Date? = nil)async throws -> UpdateCallResponse
-   @discardableResult public func reject(reason: String? = nil)async throws -> RejectCallResponse
+   @discardableResult public func accept()async throws -> AcceptCallResponse
-   @discardableResult public func block(user: User)async throws -> BlockUserResponse
+   @discardableResult public func reject(reason: String? = nil)async throws -> RejectCallResponse
-   @discardableResult public func unblock(user: User)async throws -> UnblockUserResponse
+   @discardableResult public func block(user: User)async throws -> BlockUserResponse
-   public func changeTrackVisibility(for participant: CallParticipant,isVisible: Bool)async 
+   @discardableResult public func unblock(user: User)async throws -> UnblockUserResponse
-   @discardableResult public func addMembers(members: [MemberRequest])async throws -> UpdateCallMembersResponse
+   public func changeTrackVisibility(for participant: CallParticipant,isVisible: Bool)async 
-   @discardableResult public func updateMembers(members: [MemberRequest])async throws -> UpdateCallMembersResponse
+   @discardableResult public func addMembers(members: [MemberRequest])async throws -> UpdateCallMembersResponse
-   @discardableResult public func addMembers(ids: [String])async throws -> UpdateCallMembersResponse
+   @discardableResult public func updateMembers(members: [MemberRequest])async throws -> UpdateCallMembersResponse
-   @discardableResult public func removeMembers(ids: [String])async throws -> UpdateCallMembersResponse
+   @discardableResult public func addMembers(ids: [String])async throws -> UpdateCallMembersResponse
-   public func updateTrackSize(_ trackSize: CGSize,for participant: CallParticipant)async 
+   @discardableResult public func removeMembers(ids: [String])async throws -> UpdateCallMembersResponse
-   public func setVideoFilter(_ videoFilter: VideoFilter?)
+   public func updateTrackSize(_ trackSize: CGSize,for participant: CallParticipant)async 
-   public func setAudioFilter(_ audioFilter: AudioFilter?)
+   public func setVideoFilter(_ videoFilter: VideoFilter?)
-   public func startScreensharing(type: ScreensharingType)async throws 
+   public func setAudioFilter(_ audioFilter: AudioFilter?)
-   public func stopScreensharing()async throws 
+   public func startScreensharing(type: ScreensharingType)async throws 
-   public func subscribe()-> AsyncStream<VideoEvent>
+   public func stopScreensharing()async throws 
-   public func subscribe(for event: WSEvent.Type)-> AsyncStream<WSEvent>
+   public func eventPublisher(for event: WSEvent.Type)-> AnyPublisher<WSEvent, Never>
-   public func leave()
+   public func subscribe()-> AsyncStream<VideoEvent>
-   public func startNoiseCancellation()async throws 
+   public func subscribe(for event: WSEvent.Type)-> AsyncStream<WSEvent>
-   public func stopNoiseCancellation()async throws 
+   public func leave()
-   @MainActor public func currentUserCanRequestPermissions(_ permissions: [Permission])-> Bool
+   public func startNoiseCancellation()async throws 
-   @discardableResult public func request(permissions: [Permission])async throws -> RequestPermissionResponse
+   public func stopNoiseCancellation()async throws 
-   @MainActor public func currentUserHasCapability(_ capability: OwnCapability)-> Bool
+   @MainActor public func currentUserCanRequestPermissions(_ permissions: [Permission])-> Bool
-   @discardableResult public func grant(permissions: [Permission],for userId: String)async throws -> UpdateUserPermissionsResponse
+   @discardableResult public func request(permissions: [Permission])async throws -> RequestPermissionResponse
-   @discardableResult public func grant(request: PermissionRequest)async throws -> UpdateUserPermissionsResponse
+   @MainActor public func currentUserHasCapability(_ capability: OwnCapability)-> Bool
-   @discardableResult public func revoke(permissions: [Permission],for userId: String)async throws -> UpdateUserPermissionsResponse
+   @discardableResult public func grant(permissions: [Permission],for userId: String)async throws -> UpdateUserPermissionsResponse
-   @discardableResult public func mute(userId: String,audio: Bool = true,video: Bool = true)async throws -> MuteUsersResponse
+   @discardableResult public func grant(request: PermissionRequest)async throws -> UpdateUserPermissionsResponse
-   @discardableResult public func muteAllUsers(audio: Bool = true,video: Bool = true)async throws -> MuteUsersResponse
+   @discardableResult public func revoke(permissions: [Permission],for userId: String)async throws -> UpdateUserPermissionsResponse
-   @discardableResult public func end()async throws -> EndCallResponse
+   @discardableResult public func mute(userId: String,audio: Bool = true,video: Bool = true)async throws -> MuteUsersResponse
-   @discardableResult public func blockUser(with userId: String)async throws -> BlockUserResponse
+   @discardableResult public func muteAllUsers(audio: Bool = true,video: Bool = true)async throws -> MuteUsersResponse
-   @discardableResult public func unblockUser(with userId: String)async throws -> UnblockUserResponse
+   @discardableResult public func end()async throws -> EndCallResponse
-   @discardableResult public func goLive(startHls: Bool? = nil,startRecording: Bool? = nil,startRtmpBroadcasts: Bool? = nil,startTranscription: Bool? = nil)async throws -> GoLiveResponse
+   @discardableResult public func blockUser(with userId: String)async throws -> BlockUserResponse
-   @discardableResult public func stopLive()async throws -> StopLiveResponse
+   @discardableResult public func unblockUser(with userId: String)async throws -> UnblockUserResponse
-   public func stopLive(request: StopLiveRequest)async throws -> StopLiveResponse
+   @discardableResult public func goLive(startHls: Bool? = nil,startRecording: Bool? = nil,startRtmpBroadcasts: Bool? = nil,startTranscription: Bool? = nil)async throws -> GoLiveResponse
-   @discardableResult public func startRecording()async throws -> StartRecordingResponse
+   @discardableResult public func stopLive()async throws -> StopLiveResponse
-   @discardableResult public func stopRecording()async throws -> StopRecordingResponse
+   public func stopLive(request: StopLiveRequest)async throws -> StopLiveResponse
-   public func listRecordings()async throws -> [CallRecording]
+   @discardableResult public func startRecording()async throws -> StartRecordingResponse
-   @discardableResult public func startHLS()async throws -> StartHLSBroadcastingResponse
+   @discardableResult public func stopRecording()async throws -> StopRecordingResponse
-   @discardableResult public func stopHLS()async throws -> StopHLSBroadcastingResponse
+   public func listRecordings()async throws -> [CallRecording]
-   @discardableResult public func startRTMPBroadcast(request: StartRTMPBroadcastsRequest)async throws -> StartRTMPBroadcastsResponse
+   @discardableResult public func startHLS()async throws -> StartHLSBroadcastingResponse
-   @discardableResult public func stopRTMPBroadcasts(name: String)async throws -> StopRTMPBroadcastsResponse
+   @discardableResult public func stopHLS()async throws -> StopHLSBroadcastingResponse
-   @discardableResult public func sendCustomEvent(_ data: [String: RawJSON])async throws -> SendEventResponse
+   @discardableResult public func startRTMPBroadcast(request: StartRTMPBroadcastsRequest)async throws -> StartRTMPBroadcastsResponse
-   @discardableResult public func sendReaction(type: String,custom: [String: RawJSON]? = nil,emojiCode: String? = nil)async throws -> SendReactionResponse
+   @discardableResult public func stopRTMPBroadcasts(name: String)async throws -> StopRTMPBroadcastsResponse
-   public func queryMembers(filters: [String: RawJSON]? = nil,sort: [SortParamRequest] = [SortParamRequest.descending("created_at")],limit: Int = 25)async throws -> QueryMembersResponse
+   @discardableResult public func sendCustomEvent(_ data: [String: RawJSON])async throws -> SendEventResponse
-   public func queryMembers(filters: [String: RawJSON]? = nil,sort: [SortParamRequest]? = nil,limit: Int = 25,next: String)async throws -> QueryMembersResponse
+   @discardableResult public func sendReaction(type: String,custom: [String: RawJSON]? = nil,emojiCode: String? = nil)async throws -> SendReactionResponse
-   public func pin(sessionId: String)async throws 
+   public func queryMembers(filters: [String: RawJSON]? = nil,sort: [SortParamRequest] = [SortParamRequest.descending("created_at")],limit: Int = 25)async throws -> QueryMembersResponse
-   public func unpin(sessionId: String)async throws 
+   public func queryMembers(filters: [String: RawJSON]? = nil,sort: [SortParamRequest]? = nil,limit: Int = 25,next: String)async throws -> QueryMembersResponse
-   public func pinForEveryone(userId: String,sessionId: String)async throws -> PinResponse
+   public func pin(sessionId: String)async throws 
-   public func unpinForEveryone(userId: String,sessionId: String)async throws -> UnpinResponse
+   public func unpin(sessionId: String)async throws 
-   public func focus(at point: CGPoint)async throws 
+   public func pinForEveryone(userId: String,sessionId: String)async throws -> PinResponse
-   public func addCapturePhotoOutput(_ capturePhotoOutput: AVCapturePhotoOutput)async throws 
+   public func unpinForEveryone(userId: String,sessionId: String)async throws -> UnpinResponse
-   public func removeCapturePhotoOutput(_ capturePhotoOutput: AVCapturePhotoOutput)async throws 
+   public func focus(at point: CGPoint)async throws 
-   @available(iOS 16.0, *) public func addVideoOutput(_ videoOutput: AVCaptureVideoDataOutput)async throws 
+   public func addCapturePhotoOutput(_ capturePhotoOutput: AVCapturePhotoOutput)async throws 
-   @available(iOS 16.0, *) public func removeVideoOutput(_ videoOutput: AVCaptureVideoDataOutput)async throws 
+   public func removeCapturePhotoOutput(_ capturePhotoOutput: AVCapturePhotoOutput)async throws 
-   public func zoom(by factor: CGFloat)async throws 
+   @available(iOS 16.0, *) public func addVideoOutput(_ videoOutput: AVCaptureVideoDataOutput)async throws 
-   @discardableResult public func startTranscription(transcriptionExternalStorage: String? = nil)async throws -> StartTranscriptionResponse
+   @available(iOS 16.0, *) public func removeVideoOutput(_ videoOutput: AVCaptureVideoDataOutput)async throws 
-   @discardableResult public func stopTranscription(stopClosedCaptions: Bool? = nil)async throws -> StopTranscriptionResponse
+   public func zoom(by factor: CGFloat)async throws 
-   @discardableResult @MainActor public func collectUserFeedback(rating: Int,reason: String? = nil,custom: [String: RawJSON]? = nil)async throws -> CollectUserFeedbackResponse
+   @discardableResult public func startTranscription(transcriptionExternalStorage: String? = nil)async throws -> StartTranscriptionResponse
-   @MainActor public func updateParticipantsSorting(with sortComparators: [StreamSortComparator<CallParticipant>])
+   @discardableResult public func stopTranscription(stopClosedCaptions: Bool? = nil)async throws -> StopTranscriptionResponse
-   @MainActor public func setIncomingVideoQualitySettings(_ value: IncomingVideoQualitySettings)async 
+   @discardableResult @MainActor public func collectUserFeedback(rating: Int,reason: String? = nil,custom: [String: RawJSON]? = nil)async throws -> CollectUserFeedbackResponse
-   public func setDisconnectionTimeout(_ timeout: TimeInterval)
+   @MainActor public func updateParticipantsSorting(with sortComparators: [StreamSortComparator<CallParticipant>])
-   public func updatePublishOptions(preferredVideoCodec: VideoCodec,maxBitrate: Int = .maxBitrate)async 
+   @MainActor public func setIncomingVideoQualitySettings(_ value: IncomingVideoQualitySettings)async 
-   @discardableResult public func startClosedCaptions(_ request: StartClosedCaptionsRequest = .init())async throws -> StartClosedCaptionsResponse
+   public func setDisconnectionTimeout(_ timeout: TimeInterval)
-   @discardableResult public func stopClosedCaptions(stopTranscription: Bool? = nil)async throws -> StopClosedCaptionsResponse
+   public func updatePublishOptions(preferredVideoCodec: VideoCodec,maxBitrate: Int = .maxBitrate)async 
-   @MainActor public func updateClosedCaptionsSettings(itemPresentationDuration: TimeInterval,maxVisibleItems: Int)async 
+   @discardableResult public func startClosedCaptions(_ request: StartClosedCaptionsRequest = .init())async throws -> StartClosedCaptionsResponse
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   @discardableResult public func stopClosedCaptions(stopTranscription: Bool? = nil)async throws -> StopClosedCaptionsResponse
+   @MainActor public func updateClosedCaptionsSettings(itemPresentationDuration: TimeInterval,maxVisibleItems: Int)async 
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws

 @MainActor open class CallViewModel: ObservableObject  
-   public func setActiveCall(_ call: Call?)
+   public func setActiveCall(_ call: Call?,file: StaticString = #file,function: StaticString = #function,line: UInt = #line)

 public class Sounds  
-   public var outgoingCallSound
+   public var outgoingCallSound: Resource
-   public var incomingCallSound
+   public var incomingCallSound: Resource

 public final class CallSettings: ObservableObject, Sendable, Equatable, ReflectiveStringConvertible  
-   public init(audioOn: Bool = true,videoOn: Bool = true,speakerOn: Bool = true,audioOutputOn: Bool = true,cameraPosition: CameraPosition = .front)
+   public convenience init(_ response: CallSettingsResponse,file: StaticString = #file,function: StaticString = #function,line: UInt = #line)
-   
+   public init(audioOn: Bool = true,videoOn: Bool = true,speakerOn: Bool = true,audioOutputOn: Bool = true,cameraPosition: CameraPosition = .front,file: StaticString = #file,function: StaticString = #function,line: UInt = #line)
- 
+   
-   public static func ==(lhs: CallSettings,rhs: CallSettings)-> Bool
+ 
+   public static func ==(lhs: CallSettings,rhs: CallSettings)-> Bool

 public struct IncomingCall: Identifiable, Sendable, Equatable  
-   
+   public let custom: [String: RawJSON]
- 
+   
-   public init(id: String,caller: User,type: String,members: [Member],timeout: TimeInterval,video: Bool = false)
+ 
-   
+   public init(id: String,caller: User,type: String,members: [Member],timeout: TimeInterval,video: Bool = false,custom: [String: RawJSON] = [:])
- 
+   
-   public static func ==(lhs: IncomingCall,rhs: IncomingCall)-> Bool
+ 
+   public static func ==(lhs: IncomingCall,rhs: IncomingCall)-> Bool

 public struct LogSubsystem: OptionSet, CustomStringConvertible, Sendable  
-   public var description: String
+   public static let callKit
-   
+   public var description: String
- 
+   
-   public init(rawValue: Int)
+ 
+   public init(rawValue: Int)

 public struct Colors  
-   public var participantSpeakingHighlightColor
+   public var livestreamText
-   public var participantInfoBackgroundColor
+   public var participantSpeakingHighlightColor
-   public var callDurationColor: UIColor
+   public var participantInfoBackgroundColor
-   public var goodConnectionQualityIndicatorColor
+   public var callDurationColor: UIColor
-   public var badConnectionQualityIndicatorColor
+   public var goodConnectionQualityIndicatorColor
-   public var activeSecondaryCallControl
+   public var badConnectionQualityIndicatorColor
-   public var inactiveCallControl
+   public var activeSecondaryCallControl
-   
+   public var inactiveCallControl
- 
+   
-   public init()
+ 
+   public init()

 public final class CurrentDevice: @unchecked Sendable  
-   public private var deviceType: DeviceType
+   public internal var deviceType: DeviceType
-   public private var systemVersion: String
+   public internal var systemVersion: String

- public enum CallingState: Equatable  
+ public enum CallingState: Equatable, CustomStringConvertible  
+   
+ 
+   public var description: String

Copy link

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@Stream-SDK-Bot
Copy link
Collaborator Author

SDK Size

title previous release current release diff status
StreamVideo 7.6 MB 7.62 MB +20 KB 🟢
StreamVideoSwiftUI 2.09 MB 2.25 MB +159 KB 🟢
StreamVideoUIKit 2.23 MB 2.38 MB +159 KB 🟢
StreamWebRTC 9.85 MB 9.85 MB 0 KB 🟢

Copy link

Build for regression testing №206 has been uploaded to TestFlight 🎁

Copy link

@ipavlidakis
Copy link
Contributor

/merge release

@github-actions github-actions bot merged commit 048a72d into main Apr 22, 2025
15 checks passed
@testableapple
Copy link
Contributor

Publication of the release has been launched 👍

@github-actions github-actions bot deleted the release/1.21.0 branch April 22, 2025 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants