Skip to content

Commit 9c85357

Browse files
authored
[Fix]Mistakenly prompting for permissions (#988)
1 parent b624d14 commit 9c85357

File tree

5 files changed

+73
-8
lines changed

5 files changed

+73
-8
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
44

55
# Upcoming
66

7+
### 🐞 Fixed
8+
- Fix permission prompts appearing when not needed. [#988](https://github.com/GetStream/stream-video-swift/pull/988)
9+
710
### ✅ Added
811
- SwiftUI modifiers that surface moderation blur and warning events in `CallView`. [#987](https://github.com/GetStream/stream-video-swift/pull/987)
912

Sources/StreamVideo/WebRTC/PeerConnectionFactory.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final class PeerConnectionFactory: @unchecked Sendable {
2020
)
2121
let decoderFactory = RTCDefaultVideoDecoderFactory()
2222
return RTCPeerConnectionFactory(
23-
audioDeviceModuleType: .platformDefault,
23+
audioDeviceModuleType: .audioEngine,
2424
bypassVoiceProcessing: false,
2525
encoderFactory: encoderFactory,
2626
decoderFactory: decoderFactory,

Sources/StreamVideo/WebRTC/v2/WebRTCPermissionsAdapter.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ final class WebRTCPermissionsAdapter: @unchecked Sendable {
5252
private weak var delegate: WebRTCPermissionsAdapterDelegate?
5353
private var requiredPermissions: Set<RequiredPermission> = []
5454
private var lastCallSettings: CallSettings?
55+
private var ownCapabilities: Set<OwnCapability> = []
5556

5657
/// Creates an adapter and begins observing app/permission changes.
5758
///
@@ -155,6 +156,12 @@ final class WebRTCPermissionsAdapter: @unchecked Sendable {
155156
}
156157
}
157158

159+
func willSet(ownCapabilities: Set<OwnCapability>) {
160+
processingQueue.addOperation { [weak self] in
161+
self?.ownCapabilities = ownCapabilities
162+
}
163+
}
164+
158165
func cleanUp() {
159166
processingQueue.addOperation { [weak self] in
160167
// By emptying the Set we are saying that there are no permissions
@@ -237,9 +244,11 @@ final class WebRTCPermissionsAdapter: @unchecked Sendable {
237244

238245
switch permission {
239246
case .microphone:
240-
return !permissions.hasMicrophonePermission && permissions.canRequestMicrophonePermission
247+
return !permissions.hasMicrophonePermission && permissions.canRequestMicrophonePermission && ownCapabilities
248+
.contains(.sendAudio)
241249
case .camera:
242-
return !permissions.hasCameraPermission && permissions.canRequestCameraPermission
250+
return !permissions.hasCameraPermission && permissions.canRequestCameraPermission && ownCapabilities
251+
.contains(.sendVideo)
243252
}
244253
}
245254
}

Sources/StreamVideo/WebRTC/v2/WebRTCStateAdapter.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,10 @@ actor WebRTCStateAdapter: ObservableObject, StreamAudioSessionAdapterDelegate, W
165165
func set(connectOptions value: ConnectOptions) { self.connectOptions = value }
166166

167167
/// Sets the own capabilities of the current user.
168-
func set(ownCapabilities value: Set<OwnCapability>) { self.ownCapabilities = value }
168+
func set(ownCapabilities value: Set<OwnCapability>) {
169+
self.ownCapabilities = value
170+
permissionsAdapter.willSet(ownCapabilities: value)
171+
}
169172

170173
/// Sets the WebRTC stats reporter.
171174
func set(statsAdapter value: WebRTCStatsAdapting?) {

StreamVideoTests/WebRTC/v2/WebRTCPermissionsAdapter_Tests.swift

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class WebRTCPermissionsAdapter_Tests: StreamVideoTestCase, @unchecked Send
2222
super.tearDown()
2323
}
2424

25-
func test_willSet_audioOnTrue_withDeniedMic_downgradesAudioOff() async {
25+
func test_willSet_audioOnTrue_withoutSendAudio_withDeniedMic_downgradesAudioOff() async {
2626
mockAppStateAdapter.makeShared()
2727
mockPermissions.stubMicrophonePermission(.denied)
2828
await fulfillment { self.mockPermissions.mockStore.state.microphonePermission == .denied }
@@ -34,7 +34,33 @@ final class WebRTCPermissionsAdapter_Tests: StreamVideoTestCase, @unchecked Send
3434
XCTAssertEqual(output.videoOn, false)
3535
}
3636

37-
func test_willSet_videoOnTrue_withDeniedCamera_downgradesVideoOff() async {
37+
func test_willSet_audioOnTrue_withSendAudio_withDeniedMic_downgradesAudioOff() async {
38+
mockAppStateAdapter.makeShared()
39+
mockPermissions.stubMicrophonePermission(.denied)
40+
await fulfillment { self.mockPermissions.mockStore.state.microphonePermission == .denied }
41+
42+
let input = CallSettings(audioOn: true, videoOn: false)
43+
subject.willSet(ownCapabilities: [.sendAudio])
44+
let output = await subject.willSet(callSettings: input)
45+
46+
XCTAssertEqual(output.audioOn, false)
47+
XCTAssertEqual(output.videoOn, false)
48+
}
49+
50+
func test_willSet_videoOnTrue_withSendVideo_withDeniedCamera_downgradesVideoOff() async {
51+
mockAppStateAdapter.makeShared()
52+
mockPermissions.stubCameraPermission(.denied)
53+
await fulfillment { self.mockPermissions.mockStore.state.cameraPermission == .denied }
54+
55+
let input = CallSettings(audioOn: false, videoOn: true)
56+
subject.willSet(ownCapabilities: [.sendVideo])
57+
let output = await subject.willSet(callSettings: input)
58+
59+
XCTAssertEqual(output.audioOn, false)
60+
XCTAssertEqual(output.videoOn, false)
61+
}
62+
63+
func test_willSet_videoOnTrue_withoutSendVideo_withDeniedCamera_downgradesVideoOff() async {
3864
mockAppStateAdapter.makeShared()
3965
mockPermissions.stubCameraPermission(.denied)
4066
await fulfillment { self.mockPermissions.mockStore.state.cameraPermission == .denied }
@@ -46,10 +72,22 @@ final class WebRTCPermissionsAdapter_Tests: StreamVideoTestCase, @unchecked Send
4672
XCTAssertEqual(output.videoOn, false)
4773
}
4874

49-
func test_willSet_audioOnTrue_unknownMic_inForeground_requestsPermission_andKeepsAudioOnWhenGranted() async {
75+
func test_willSet_audioOnTrue_unknownMic_inForeground_withoutSendAudio_requestsPermission_andKeepsAudioOnWhenGranted() async {
76+
mockAppStateAdapter.makeShared()
77+
mockAppStateAdapter.stubbedState = .foreground
78+
mockPermissions.stubMicrophonePermission(.unknown)
79+
await fulfillment { self.mockPermissions.mockStore.state.microphonePermission == .unknown }
80+
81+
let input = CallSettings(audioOn: true, videoOn: false)
82+
let output = await self.subject.willSet(callSettings: input)
83+
XCTAssertEqual(output.audioOn, false)
84+
}
85+
86+
func test_willSet_audioOnTrue_unknownMic_inForeground_withSendAudio_requestsPermission_andKeepsAudioOnWhenGranted() async {
5087
mockAppStateAdapter.makeShared()
5188
mockAppStateAdapter.stubbedState = .foreground
5289
mockPermissions.stubMicrophonePermission(.unknown)
90+
subject.willSet(ownCapabilities: [.sendAudio])
5391
await fulfillment { self.mockPermissions.mockStore.state.microphonePermission == .unknown }
5492

5593
await withTaskGroup(of: Void.self) { group in
@@ -71,10 +109,22 @@ final class WebRTCPermissionsAdapter_Tests: StreamVideoTestCase, @unchecked Send
71109
}
72110
}
73111

74-
func test_willSet_videoOnTrue_unknownCamera_inForeground_requestsPermission_andKeepsVideoOnWhenGranted() async {
112+
func test_willSet_videoOnTrue_unknownCamera_inForeground_withoutSendVideo_requestsPermission_andKeepsVideoOnWhenGranted() async {
113+
mockAppStateAdapter.makeShared()
114+
mockAppStateAdapter.stubbedState = .foreground
115+
mockPermissions.stubCameraPermission(.unknown)
116+
await fulfillment { self.mockPermissions.mockStore.state.cameraPermission == .unknown }
117+
118+
let input = CallSettings(audioOn: false, videoOn: true)
119+
let output = await self.subject.willSet(callSettings: input)
120+
XCTAssertEqual(output.videoOn, false)
121+
}
122+
123+
func test_willSet_videoOnTrue_unknownCamera_inForeground_withSendVideo_requestsPermission_andKeepsVideoOnWhenGranted() async {
75124
mockAppStateAdapter.makeShared()
76125
mockAppStateAdapter.stubbedState = .foreground
77126
mockPermissions.stubCameraPermission(.unknown)
127+
subject.willSet(ownCapabilities: [.sendVideo])
78128
await fulfillment { self.mockPermissions.mockStore.state.cameraPermission == .unknown }
79129

80130
await withTaskGroup(of: Void.self) { group in

0 commit comments

Comments
 (0)