Skip to content

[Enhancement]Implement proximity policies #770

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

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

ipavlidakis
Copy link
Contributor

@ipavlidakis ipavlidakis commented Apr 24, 2025

🔗 Issue Links

Resolves https://linear.app/stream/issue/IOS-827/[feature-request]proximity-for-calls

🎯 Goal

Provide proximity based operations during a call.

🛠 Implementation

We introduce a new protocol ProximityPolicy that can be used to define what will happen when the device's proximity change during a call. You can attach ProximityPolicy instances on any Call object.

Out of the box, the SDK ships with the following ProximityPolicy implementations:

  • SpeakerProximityPolicy: If speaker is enabled when proximity changes to near the policy will switch to earpiece. It will then restore speaker when proximity changes to far.
  • VideoProximityPolicy: The policy disables all video (remote and local) when proximity changes to near and restores everything back when proximity changes to far.

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change follows zero ⚠️ policy (required)
  • This change should receive manual QA
  • Changelog is updated with client-facing changes
  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (tutorial, CMS)

@ipavlidakis ipavlidakis added the enhancement New feature or request label Apr 24, 2025
@ipavlidakis ipavlidakis self-assigned this Apr 24, 2025
@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Apr 24, 2025

SDK Size

title develop branch diff status
StreamVideo 7.48 MB 7.52 MB +41 KB 🟢
StreamVideoSwiftUI 2.25 MB 2.25 MB 0 KB 🟢
StreamVideoUIKit 2.37 MB 2.37 MB 0 KB 🟢
StreamWebRTC 9.85 MB 9.85 MB 0 KB 🟢

Copy link

Public Interface

+ public final class SpeakerProximityPolicy: ProximityPolicy, Hashable, @unchecked Sendable  
+ 
+   public let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public static func ==(lhs: SpeakerProximityPolicy,rhs: SpeakerProximityPolicy)-> Bool
+   public func hash(into hasher: inout Hasher)
+   public func attach(on call: Call)
+   public func detach()

+ public final class VideoProximityPolicy: ProximityPolicy, Hashable, @unchecked Sendable  
+ 
+   public let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public static func ==(lhs: VideoProximityPolicy,rhs: VideoProximityPolicy)-> Bool
+   public func hash(into hasher: inout Hasher)
+   public func attach(on call: Call)
+   public func detach()

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near, far

+ public protocol ProximityPolicy: Sendable, Hashable



 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

Copy link

github-actions bot commented Apr 24, 2025

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

Copy link

Public Interface

+ public final class SpeakerProximityPolicy: ProximityPolicy, Hashable, @unchecked Sendable  
+ 
+   public let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public static func ==(lhs: SpeakerProximityPolicy,rhs: SpeakerProximityPolicy)-> Bool
+   public func hash(into hasher: inout Hasher)
+   public func attach(on call: Call)
+   public func detach()

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near, far

+ public final class VideoProximityPolicy: ProximityPolicy, Hashable, @unchecked Sendable  
+ 
+   public let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public static func ==(lhs: VideoProximityPolicy,rhs: VideoProximityPolicy)-> Bool
+   public func hash(into hasher: inout Hasher)
+   public func attach(on call: Call)
+   public func detach()

+ extension ProximityMonitor: InjectionKey  
+ 
+   nonisolated public static var currentValue: ProximityMonitor

+ public final class ProximityMonitor: ObservableObject, @unchecked Sendable  
+ 
+   @MainActor public func startObservation()
+   public func stopObservation()

+ public protocol ProximityPolicy: Sendable, Hashable



 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

@ipavlidakis ipavlidakis force-pushed the enhancement/implement-proximity-audio-output-switch branch from 5c803ab to 1a8a4d4 Compare April 25, 2025 10:09
Copy link

Public Interface

+ public final class SpeakerProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ public final class VideoProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ public protocol ProximityPolicy: Sendable, CustomStringConvertible

+ public final class ProximityMonitor: ObservableObject, @unchecked Sendable  
+ 
+   @MainActor public func startObservation()
+   public func stopObservation()

+ extension ProximityPolicy  
+ 
+   public var description: String

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near, far

+ extension ProximityMonitor: InjectionKey  
+ 
+   nonisolated public static var currentValue: ProximityMonitor



 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)throws 
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

@ipavlidakis ipavlidakis force-pushed the enhancement/implement-proximity-audio-output-switch branch from dafcec1 to feacae7 Compare April 25, 2025 14:54
Copy link

Public Interface

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near
+   case far

+ public protocol ProximityProviding

+ public final class VideoProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ public final class SpeakerProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ public protocol ProximityPolicy: Sendable, CustomStringConvertible

+ extension ProximityPolicy  
+ 
+   public var description: String



 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)throws 
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

@ipavlidakis ipavlidakis marked this pull request as ready for review April 25, 2025 14:59
@ipavlidakis ipavlidakis requested a review from a team as a code owner April 25, 2025 14:59
@ipavlidakis ipavlidakis force-pushed the enhancement/implement-proximity-audio-output-switch branch from feacae7 to 49130f2 Compare April 29, 2025 11:22
Copy link

Public Interface

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near
+   case far

+ extension ProximityPolicy  
+ 
+   public var description: String

+ public protocol ProximityProviding

+ public final class SpeakerProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ public protocol ProximityPolicy: Sendable, CustomStringConvertible

+ public final class VideoProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)



 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)throws 
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

@ipavlidakis ipavlidakis force-pushed the enhancement/implement-proximity-audio-output-switch branch from 49130f2 to 3ef6705 Compare April 29, 2025 16:31
Copy link

Public Interface

+ public protocol ProximityProviding

+ public final class VideoProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ extension ProximityPolicy  
+ 
+   public var description: String

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near
+   case far

+ public protocol ProximityPolicy: Sendable, CustomStringConvertible

+ public final class SpeakerProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)



 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)throws 
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

@ipavlidakis ipavlidakis force-pushed the enhancement/implement-proximity-audio-output-switch branch from 3ef6705 to 8127e8a Compare April 29, 2025 18:46
Copy link

Public Interface

+ public enum ProximityState: Hashable, Sendable  
+ 
+   case near
+   case far

+ public final class SpeakerProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)

+ extension ProximityPolicy  
+ 
+   public var description: String

+ public protocol ProximityPolicy: Sendable, CustomStringConvertible

+ public protocol ProximityProviding

+ public final class VideoProximityPolicy: ProximityPolicy, @unchecked Sendable  
+ 
+   public static let identifier: ObjectIdentifier
+   
+ 
+   public init()
+   
+ 
+   public func didUpdateProximity(_ proximity: ProximityState,on call: Call)



 public final class CurrentDevice: @unchecked Sendable  
-   
+   @MainActor public var isProximityMonitoringEnabled: Bool
- 
+   
-   public enum DeviceType: Sendable  
+ 
-   
+   public enum DeviceType: Sendable  
-     case unspecified
+   
-     case phone
+     case unspecified
-     case pad
+     case phone
-     case tv
+     case pad
-     case carPlay
+     case tv
-     case mac
+     case carPlay
-     case vision
+     case mac
+     case vision

 public class Call: @unchecked Sendable, WSEventsSubscriber  
-   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws
+   public func updateAudioSessionPolicy(_ policy: AudioSessionPolicy)async throws 
+   public func addProximityPolicy(_ policy: any ProximityPolicy)throws 
+   public func removeProximityPolicy(_ policy: any ProximityPolicy)

Copy link
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition! Just one question (see comments). Additionally, we should add some docs about this.

@@ -108,7 +108,6 @@ open class CallViewModel: ObservableObject {
@Published public private(set) var callParticipants = [String: CallParticipant]() {
didSet {
updateCallStateIfNeeded()
checkCallSettingsForCurrentUser()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we had this for cases where an admin mutes you remotely. Do you think this might break it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants