diff --git a/Packages/StreamVideo/DocsCodeSamples/03-guides/CallParticipantsPinning.cs b/Packages/StreamVideo/DocsCodeSamples/03-guides/CallParticipantsPinning.cs
new file mode 100644
index 00000000..65b601b2
--- /dev/null
+++ b/Packages/StreamVideo/DocsCodeSamples/03-guides/CallParticipantsPinning.cs
@@ -0,0 +1,75 @@
+using System.Linq;
+using System.Threading.Tasks;
+using StreamVideo.Core;
+
+namespace DocsCodeSamples._03_guides
+{
+ ///
+ /// Code examples for guides/pinning-participants/ page
+ ///
+ internal class CallParticipantsPinning
+ {
+ public async Task PinLocally()
+ {
+ var callType = StreamCallType.Default; // Call type affects default permissions
+ var callId = "my-call-id";
+
+ // Get call or create if it doesn't exist
+ var streamCall = await _client.GetOrCreateCallAsync(callType, callId);
+
+ var participant = streamCall.Participants.First();
+
+ streamCall.PinLocally(participant);
+ }
+
+ public async Task UnpinLocally()
+ {
+ var callType = StreamCallType.Default; // Call type affects default permissions
+ var callId = "my-call-id";
+
+ // Get call or create if it doesn't exist
+ var streamCall = await _client.GetOrCreateCallAsync(callType, callId);
+
+ var participant = streamCall.Participants.First();
+
+ streamCall.UnpinLocally(participant);
+ }
+
+ public async Task GetPinnedParticipants()
+ {
+ var callType = StreamCallType.Default; // Call type affects default permissions
+ var callId = "my-call-id";
+
+ // Get call or create if it doesn't exist
+ var streamCall = await _client.GetOrCreateCallAsync(callType, callId);
+
+ var participant = streamCall.Participants.First();
+
+ streamCall.PinLocally(participant);
+
+ foreach (var pinnedParticipant in streamCall.PinnedParticipants)
+ {
+ // Iterate through pinned participants
+ }
+ }
+
+ public async Task CheckIfParticipantIsPinned()
+ {
+ var callType = StreamCallType.Default; // Call type affects default permissions
+ var callId = "my-call-id";
+
+ // Get call or create if it doesn't exist
+ var streamCall = await _client.GetOrCreateCallAsync(callType, callId);
+
+ var participant = streamCall.Participants.First();
+
+ streamCall.PinLocally(participant);
+
+ var isPinned = streamCall.IsPinnedLocally(participant);
+ var isPinnedLocally = streamCall.IsPinnedLocally(participant);
+ var isPinnedRemotely = streamCall.IsPinnedRemotely(participant);
+ }
+
+ private IStreamVideoClient _client;
+ }
+}
\ No newline at end of file
diff --git a/Packages/StreamVideo/DocsCodeSamples/03-guides/CallParticipantsPinning.cs.meta b/Packages/StreamVideo/DocsCodeSamples/03-guides/CallParticipantsPinning.cs.meta
new file mode 100644
index 00000000..ba69b719
--- /dev/null
+++ b/Packages/StreamVideo/DocsCodeSamples/03-guides/CallParticipantsPinning.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 353b522c69754cd0b15fd665fd90cbe6
+timeCreated: 1703167305
\ No newline at end of file
diff --git a/Packages/StreamVideo/Runtime/Core/StatefulModels/IStreamCall.cs b/Packages/StreamVideo/Runtime/Core/StatefulModels/IStreamCall.cs
index 95b1c43a..832d2dbb 100644
--- a/Packages/StreamVideo/Runtime/Core/StatefulModels/IStreamCall.cs
+++ b/Packages/StreamVideo/Runtime/Core/StatefulModels/IStreamCall.cs
@@ -251,5 +251,23 @@ Task QueryMembersAsync(IEnumerable filters
///
/// Participant to unpin
void UnpinLocally(IStreamVideoCallParticipant participant);
+
+ ///
+ /// Check if this participant is pinned locally. Also check & .
+ ///
+ /// True if participant is pinned locally
+ bool IsPinnedLocally(IStreamVideoCallParticipant participant);
+
+ ///
+ /// Check if this participant is pinned remotely. Also check & .
+ ///
+ /// True if participant is pinned remotely
+ bool IsPinnedRemotely(IStreamVideoCallParticipant participant);
+
+ ///
+ /// Check if this participant is pinned. Also check & .
+ ///
+ /// True if participant is pinned remotely
+ bool IsPinned(IStreamVideoCallParticipant participant);
}
}
\ No newline at end of file
diff --git a/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamCall.cs b/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamCall.cs
index d8e45def..0f5b7db4 100644
--- a/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamCall.cs
+++ b/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamCall.cs
@@ -340,7 +340,6 @@ public Task SendCustomEventAsync(Dictionary eventData)
// {
// return Task.CompletedTask; //StreamTodo: implement
// }
-
public Task AcceptAsync() => LowLevelClient.InternalVideoClientApi.AcceptCallAsync(Type, Id);
public Task RejectAsync() => LowLevelClient.InternalVideoClientApi.RejectCallAsync(Type, Id);
@@ -370,6 +369,15 @@ public void UnpinLocally(IStreamVideoCallParticipant participant)
UpdateSortedParticipants();
}
+ public bool IsPinnedLocally(IStreamVideoCallParticipant participant)
+ => _localPinsSessionIds.Contains(participant.SessionId);
+
+ public bool IsPinnedRemotely(IStreamVideoCallParticipant participant)
+ => _serverPinsSessionIds.Contains(participant.SessionId);
+
+ public bool IsPinned(IStreamVideoCallParticipant participant)
+ => IsPinnedLocally(participant) || IsPinnedRemotely(participant);
+
void IUpdateableFrom.UpdateFromDto(CallResponseInternalDTO dto,
ICache cache)
{
@@ -466,7 +474,7 @@ internal void UpdateFromSfu(ParticipantLeft participantLeft, ICache cache)
UpdateSortedParticipants();
cache.CallParticipants.TryRemove(participant.sessionId);
-
+
//StreamTodo: if we delete the participant from cache we should then pass SessionId and UserId
ParticipantLeft?.Invoke(participant.sessionId, participant.userId);
}
@@ -543,15 +551,15 @@ private void UpdatePinnedParticipants()
//StreamTodo: use hashset pool to optimize
foreach (var participant in Participants)
{
- if (_localPinsSessionIds.Contains(participant.SessionId))
+ if (_serverPinsSessionIds.Contains(participant.SessionId))
{
_pinnedParticipants.Add(participant);
}
}
-
+
foreach (var participant in Participants)
{
- if (_serverPinsSessionIds.Contains(participant.SessionId))
+ if (_localPinsSessionIds.Contains(participant.SessionId))
{
_pinnedParticipants.Add(participant);
}
diff --git a/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamVideoCallParticipant.cs b/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamVideoCallParticipant.cs
index 78db2bf9..fa941ed3 100644
--- a/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamVideoCallParticipant.cs
+++ b/Packages/StreamVideo/Runtime/Core/StatefulModels/StreamVideoCallParticipant.cs
@@ -8,7 +8,6 @@
using StreamVideo.Core.StatefulModels.Tracks;
using StreamVideo.Core.Utils;
using Unity.WebRTC;
-using UnityEngine;
using Participant = Stream.Video.v1.Sfu.Models.Participant;
namespace StreamVideo.Core.StatefulModels
@@ -128,7 +127,7 @@ internal void SetTrack(TrackType type, MediaStreamTrack mediaStreamTrack, out IS
{
#if STREAM_DEBUG_ENABLED
- Debug.LogWarning(
+ Logs.Warning(
$"[Participant] Local: {IsLocalParticipant} Session ID: {SessionId} set track of type {type}");
#endif
diff --git a/docusaurus/docs/Unity/03-guides/09-pinning-call-participants.mdx b/docusaurus/docs/Unity/03-guides/09-pinning-call-participants.mdx
new file mode 100644
index 00000000..472f879d
--- /dev/null
+++ b/docusaurus/docs/Unity/03-guides/09-pinning-call-participants.mdx
@@ -0,0 +1,41 @@
+---
+title: Pinning participants
+description: How to pin participants
+---
+
+The StreamVideo SDK has support for pinning users, both locally for the current user, and remotely for everyone in the call.
+Every user can pin as many participants on the call as they want, and those users will be shown first in the list of participants for that user. Pinning someone for everyone in the call requires the `pinForEveryone` capability.
+By default, the pinned users appear first in the `streamCall.SortedParticipants` array. The ones which are pinned remotely appear before the local ones. If there are several remotely pinned users, they are sorted by the pinning date (the most recent pins appear first).
+
+### Local pins
+In order to pin a user locally:
+
+```csharp
+streamCall.PinLocally(participant);
+```
+
+To unpin the user:
+```csharp
+streamCall.UnpinLocally(participant);
+```
+
+In both examples, the `participant` is an object of type `IStreamVideoCallParticipant`.
+
+To get all pinned participants:
+```csharp
+foreach (var pinnedParticipant in streamCall.PinnedParticipants)
+{
+ // Iterate through pinned participants
+}
+```
+
+You can check if the participant is pinned either locally or remotely by:
+```csharp
+var isPinned = streamCall.IsPinnedLocally(participant);
+```
+
+Or to distinguish whether the participant is pinned locally or remotely you can more specific versions:
+```csharp
+var isPinnedLocally = streamCall.IsPinnedLocally(participant);
+var isPinnedRemotely = streamCall.IsPinnedRemotely(participant);
+```