Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
deeffc7
Add snapshot postfix to v1.20.0
ipavlidakis Apr 7, 2025
95988c3
[CI] Delete fastlane scan logs (#750)
testableapple Apr 8, 2025
573f59a
[Fix]CallKit end call wasn't completing successfully (#752)
ipavlidakis Apr 9, 2025
1d85111
[Enhancement]Allow resetting local call settings (#751)
ipavlidakis Apr 10, 2025
6a45929
[Fix] Linter error (#755)
ipavlidakis Apr 11, 2025
38a9192
Extended the send stats request protobuf (#753)
martinmitrevski Apr 14, 2025
d147169
Livestream player updates (#754)
martinmitrevski Apr 14, 2025
d76270e
[Fix]Resource loading when used via SPM (#757)
ipavlidakis Apr 14, 2025
f4617eb
[Fix]Respect dashboard audio settings (#758)
ipavlidakis Apr 15, 2025
60bdee9
[Fix]Convert AsyncStream to Publishers > AsyncStream to break memory …
ipavlidakis Apr 15, 2025
4770a58
Added ended state in the livestream player (#761)
martinmitrevski Apr 17, 2025
6bdc1a5
Added fallback when host video is not available (#763)
martinmitrevski Apr 17, 2025
a6d496b
[Fix]AudioSession mode misconfiguration for audio-only calls (#762)
ipavlidakis Apr 17, 2025
f5c6589
Updated demo app livestream presentation logic (#764)
martinmitrevski Apr 22, 2025
8be93ca
[WIP] Update WebRTC version to enable dSYMs (#760)
testableapple Apr 22, 2025
0d71c60
[CI] Install an older ipsw version (#765)
testableapple Apr 22, 2025
e5bd154
[Enhancement]Expose custom data on IncomingCall (#766)
ipavlidakis Apr 22, 2025
bb694ae
[Enhancement]Implement static frame pipeline for PiP (#724)
ipavlidakis Apr 22, 2025
048a72d
Bump 1.21.0
Apr 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/actions/setup-ios-runtime/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ runs:
shell: bash
run: |
sudo rm -rfv ~/Library/Developer/CoreSimulator/* || true
brew install blacktop/tap/ipsw
bundle exec fastlane install_runtime ios:${{ inputs.version }}
sudo rm -rfv *.dmg || true
xcrun simctl list runtimes
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/cron-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ jobs:
INSTALL_ALLURE: true
INSTALL_VIDEO_BUDDY: true
INSTALL_YEETD: true
INSTALL_IPSW: true
SKIP_MINT_BOOTSTRAP: true
- uses: ./.github/actions/setup-ios-runtime
if: ${{ matrix.setup_runtime }}
Expand Down Expand Up @@ -154,6 +155,7 @@ jobs:
- uses: ./.github/actions/bootstrap
env:
INSTALL_YEETD: true
INSTALL_IPSW: true
- uses: ./.github/actions/setup-ios-runtime
if: ${{ matrix.setup_runtime }}
timeout-minutes: 60
Expand Down
15 changes: 2 additions & 13 deletions .github/workflows/smoke-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,6 @@ jobs:
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: LLC Test Data
path: |
~/Library/Logs/scan
- uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
Expand Down Expand Up @@ -109,9 +103,7 @@ jobs:
if: failure()
with:
name: SwiftUI Test Data
path: |
~/Library/Logs/scan
fastlane/test_output/snapshots
path: fastlane/test_output/snapshots

test-uikit-debug:
name: Test UIKit (Debug)
Expand All @@ -137,9 +129,7 @@ jobs:
if: failure()
with:
name: UIKit Test Data
path: |
~/Library/Logs/scan
fastlane/test_output/snapshots
path: fastlane/test_output/snapshots

automated-code-review:
name: Automated Code Review
Expand Down Expand Up @@ -307,7 +297,6 @@ jobs:
with:
name: E2E Test Data ${{ matrix.batch }}
path: |
~/Library/Logs/scan
fastlane/recordings
fastlane/*.log
fastlane/test_output/report.junit
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### 🔄 Changed

# [1.21.0](https://github.com/GetStream/stream-video-swift/releases/tag/1.21.0)
_April 22, 2025_

### ✅ Added
- Countdown timer and waiting participants info to the livestream player [#754](https://github.com/GetStream/stream-video-swift/pull/754)
- EventPublisher for `Call` objects. [#759](https://github.com/GetStream/stream-video-swift/pull/759)
- You can now access the `custom-data` attached on a Call object you received as incoming. [#766](https://github.com/GetStream/stream-video-swift/pull/766)

### 🔄 Changed
- `CallViewModel.callingState` transition to `.idle` just before moving to `.inCall` after the user has accepted the call. [#759](https://github.com/GetStream/stream-video-swift/pull/759)
- `AudioSession` mode wasn't configured correctly for audio-only calls. [#762](https://github.com/GetStream/stream-video-swift/pull/762)
- Updated WebRTC version to 125.6422.070 [#760](https://github.com/GetStream/stream-video-swift/pull/760)
- Picture-in-Picture improved UI and stability fixes. [#724](https://github.com/GetStream/stream-video-swift/pull/724)

### 🐞 Fixed
- Sound resources weren't loaded correctly when the SDK was linked via SPM. [#757](https://github.com/GetStream/stream-video-swift/pull/757)
- Redefined the priorities by which dashboard audio settings will be applied. [#758](https://github.com/GetStream/stream-video-swift/pull/758)

# [1.20.0](https://github.com/GetStream/stream-video-swift/releases/tag/1.20.0)
_April 07, 2025_

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ struct DemoCallModifier<Factory: ViewFactory>: ViewModifier {
private func contentView(_ rootView: Content) -> some View {
if
let call = viewModel.call,
call.callType == .livestream,
(call.currentUserHasCapability(.sendAudio) == false) || (call.currentUserHasCapability(.sendVideo) == false) {
call.callType == .livestream {
ZStack {
rootView
LivestreamPlayer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fileprivate func content() {
// Here we register for incomingCalls and provide
// a logo as we did on the previous example
// Provide the ringtone to use when a CallKit call is ringing
callKitAdapter.ringtoneSound = sounds.incomingCallSound
callKitAdapter.ringtoneSound = sounds.incomingCallSound.fileName
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Githubfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export PLAYWRIGHT_VERSION='1.41.2'
export YEETD_VERSION='1.0'
export MINT_VERSION='0.17.5'
export SONAR_VERSION='6.2.1.4610'
export IPSW_VERSION='3.1.592'
7 changes: 5 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.29.0"),
.package(url: "https://github.com/GetStream/stream-video-swift-webrtc.git", exact: "125.6422.066")
.package(url: "https://github.com/GetStream/stream-video-swift-webrtc.git", exact: "125.6422.070")
],
targets: [
.target(
Expand All @@ -35,7 +35,10 @@ let package = Package(
),
.target(
name: "StreamVideoSwiftUI",
dependencies: ["StreamVideo"]
dependencies: ["StreamVideo"],
resources: [
.process("Resources")
]
),
.target(
name: "StreamVideoUIKit",
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
<a href="https://swift.org"><img src="https://img.shields.io/badge/Swift-5.9%2B-orange.svg" /></a>
</p>
<p align="center">
<img id="stream-video-label" alt="StreamVideo" src="https://img.shields.io/badge/StreamVideo-7.6%20MB-blue"/>
<img id="stream-video-swiftui-label" alt="StreamVideoSwiftUI" src="https://img.shields.io/badge/StreamVideoSwiftUI-2.09%20MB-blue"/>
<img id="stream-video-uikit-label" alt="StreamVideoUIKit" src="https://img.shields.io/badge/StreamVideoUIKit-2.23%20MB-blue"/>
<img id="stream-video-label" alt="StreamVideo" src="https://img.shields.io/badge/StreamVideo-7.62%20MB-blue"/>
<img id="stream-video-swiftui-label" alt="StreamVideoSwiftUI" src="https://img.shields.io/badge/StreamVideoSwiftUI-2.25%20MB-blue"/>
<img id="stream-video-uikit-label" alt="StreamVideoUIKit" src="https://img.shields.io/badge/StreamVideoUIKit-2.38%20MB-blue"/>
<img id="stream-web-rtc-label" alt="StreamWebRTC" src="https://img.shields.io/badge/StreamWebRTC-9.85%20MB-blue"/>
</p>

Expand Down
9 changes: 9 additions & 0 deletions Scripts/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,12 @@ if [[ ${INSTALL_YEETD-default} == true ]]; then
puts "Running yeetd daemon"
yeetd &
fi

if [[ ${INSTALL_IPSW-default} == true ]]; then
puts "Install ipsw v${IPSW_VERSION}"
FILE="ipsw_${IPSW_VERSION}_macOS_universal.tar.gz"
wget "https://github.com/blacktop/ipsw/releases/download/v${IPSW_VERSION}/${FILE}"
tar -xzf "$FILE"
chmod +x ipsw
sudo mv ipsw /usr/local/bin/
fi
54 changes: 24 additions & 30 deletions Sources/StreamVideo/Call.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
callCid(from: callId, callType: callType)
}

private let eventSubject: PassthroughSubject<WrappedEvent, Never> = .init()
public var eventPublisher: AnyPublisher<VideoEvent, Never> {
eventSubject
.compactMap {
switch $0 {
case let .coordinatorEvent(event):
return event
default:
return nil
}
}
.eraseToAnyPublisher()
}

/// Provides access to the microphone.
public let microphone: MicrophoneManager
/// Provides access to the camera.
Expand All @@ -37,7 +51,6 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {

internal let callController: CallController
internal let coordinatorClient: DefaultAPI
private var eventHandlers = [EventHandler]()
private var cancellables = DisposableBag()

/// This adapter is used to manage closed captions for the
Expand Down Expand Up @@ -90,6 +103,7 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
}

deinit {
log.debug("Call cID:\(cId) is deallocating...")
cancellables.removeAll()
}

Expand Down Expand Up @@ -481,45 +495,30 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
try await callController.stopScreensharing()
}

public func eventPublisher<WSEvent: Event>(for event: WSEvent.Type) -> AnyPublisher<WSEvent, Never> {
eventPublisher
.compactMap { $0.rawValue as? WSEvent }
.eraseToAnyPublisher()
}

/// Subscribes to video events.
/// - Returns: `AsyncStream` of `VideoEvent`s.
public func subscribe() -> AsyncStream<VideoEvent> {
AsyncStream(VideoEvent.self) { [weak self] continuation in
let eventHandler = EventHandler(handler: { event in
guard case let .coordinatorEvent(event) = event else {
return
}
continuation.yield(event)
}, cancel: { continuation.finish() })
self?.eventHandlers.append(eventHandler)
}
eventPublisher.eraseAsAsyncStream()
}

/// Subscribes to a particular web socket event.
/// - Parameter event: the type of the event you are subscribing to.
/// - Returns: `AsyncStream` of web socket events from the provided type.
public func subscribe<WSEvent: Event>(for event: WSEvent.Type) -> AsyncStream<WSEvent> {
AsyncStream(event) { [weak self] continuation in
let eventHandler = EventHandler(handler: { event in
guard case let .coordinatorEvent(event) = event else {
return
}
if let event = event.rawValue as? WSEvent {
continuation.yield(event)
}
}, cancel: { continuation.finish() })

self?.eventHandlers.append(eventHandler)
}
eventPublisher(for: event).eraseAsAsyncStream()
}

/// Leave the current call.
public func leave() {
postNotification(with: CallNotification.callEnded, object: self)
eventHandlers.forEach { $0.cancel() }

cancellables.removeAll()
eventHandlers.removeAll()
callController.leave()
closedCaptionsAdapter.stop()
stateMachine.transition(.idle(self))
Expand Down Expand Up @@ -1384,12 +1383,7 @@ public class Call: @unchecked Sendable, WSEventsSubscriber {
self.state.updateState(from: videoEvent)
}

// Get a copy of eventHandlers to avoid crashes when `leave` call is being
// triggered, during event processing.
let eventHandlers = self.eventHandlers
for eventHandler in eventHandlers {
eventHandler.handler(event)
}
eventSubject.send(event)
}

@MainActor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
/// Registers for push notifications.
open func register() {
#if targetEnvironment(simulator) && !STREAM_TESTS
log.info("CallKit notifications are not supported on simulator.")
log.info("CallKit notifications are not supported on simulator.", subsystems: .callKit)
#else
registry.delegate = self
registry.desiredPushTypes = [.voIP]
Expand All @@ -62,7 +62,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
/// Unregisters for push notifications.
open func unregister() {
#if targetEnvironment(simulator) && !STREAM_TESTS
log.info("CallKit notifications are not supported on simulator.")
log.info("CallKit notifications are not supported on simulator.", subsystems: .callKit)
#else
registry.delegate = nil
registry.desiredPushTypes = []
Expand All @@ -77,7 +77,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
for type: PKPushType
) {
let deviceToken = pushCredentials.token.map { String(format: "%02x", $0) }.joined()
log.debug("Device token updated to: \(deviceToken)")
log.debug("Device token updated to: \(deviceToken)", subsystems: .callKit)
self.deviceToken = deviceToken
}

Expand All @@ -86,7 +86,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
_ registry: PKPushRegistry,
didInvalidatePushTokenFor type: PKPushType
) {
log.debug("Device token invalidated.")
log.debug("Device token invalidated.", subsystems: .callKit)
deviceToken = ""
}

Expand Down Expand Up @@ -114,7 +114,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs
hasVideo: content.hasVideo,
completion: { error in
if let error {
log.error(error)
log.error(error, subsystems: .callKit)
}
}
)
Expand Down
Loading
Loading