davidliu

mute indicators for sample app

@@ -79,12 +79,13 @@ class RemoteTrackPublication( @@ -79,12 +79,13 @@ class RemoteTrackPublication(
79 } 79 }
80 } 80 }
81 81
82 - override var muted: Boolean = false 82 + override var muted: Boolean
  83 + get() = super.muted
83 set(v) { 84 set(v) {
84 - if (field == v) { 85 + if (super.muted == v) {
85 return 86 return
86 } 87 }
87 - field = v 88 + super.muted = v
88 val participant = this.participant.get() as? RemoteParticipant ?: return 89 val participant = this.participant.get() as? RemoteParticipant ?: return
89 if (v) { 90 if (v) {
90 participant.onTrackMuted(this) 91 participant.onTrackMuted(this)
@@ -21,7 +21,9 @@ open class TrackPublication( @@ -21,7 +21,9 @@ open class TrackPublication(
21 private set 21 private set
22 var kind: Track.Kind 22 var kind: Track.Kind
23 private set 23 private set
24 - open var muted: Boolean = false 24 +
  25 + @get:FlowObservable
  26 + open var muted: Boolean by flowDelegate(false)
25 internal set 27 internal set
26 open val subscribed: Boolean 28 open val subscribed: Boolean
27 get() { 29 get() {
@@ -8,8 +8,14 @@ import io.livekit.android.room.Room @@ -8,8 +8,14 @@ import io.livekit.android.room.Room
8 import io.livekit.android.room.participant.Participant 8 import io.livekit.android.room.participant.Participant
9 import io.livekit.android.room.participant.ParticipantListener 9 import io.livekit.android.room.participant.ParticipantListener
10 import io.livekit.android.room.participant.RemoteParticipant 10 import io.livekit.android.room.participant.RemoteParticipant
11 -import io.livekit.android.room.track.* 11 +import io.livekit.android.room.track.RemoteTrackPublication
  12 +import io.livekit.android.room.track.Track
  13 +import io.livekit.android.room.track.VideoTrack
12 import io.livekit.android.sample.databinding.ParticipantItemBinding 14 import io.livekit.android.sample.databinding.ParticipantItemBinding
  15 +import io.livekit.android.util.flow
  16 +import kotlinx.coroutines.*
  17 +import kotlinx.coroutines.flow.flatMapLatest
  18 +import kotlinx.coroutines.flow.flowOf
13 19
14 class ParticipantItem( 20 class ParticipantItem(
15 val room: Room, 21 val room: Room,
@@ -17,6 +23,7 @@ class ParticipantItem( @@ -17,6 +23,7 @@ class ParticipantItem(
17 ) : BindableItem<ParticipantItemBinding>() { 23 ) : BindableItem<ParticipantItemBinding>() {
18 24
19 private var boundVideoTrack: VideoTrack? = null 25 private var boundVideoTrack: VideoTrack? = null
  26 + private var coroutineScope: CoroutineScope? = null
20 27
21 override fun initializeViewBinding(view: View): ParticipantItemBinding { 28 override fun initializeViewBinding(view: View): ParticipantItemBinding {
22 val binding = ParticipantItemBinding.bind(view) 29 val binding = ParticipantItemBinding.bind(view)
@@ -24,8 +31,34 @@ class ParticipantItem( @@ -24,8 +31,34 @@ class ParticipantItem(
24 return binding 31 return binding
25 } 32 }
26 33
  34 + private fun ensureCoroutineScope() {
  35 + if (coroutineScope == null) {
  36 + coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
  37 + }
  38 + }
  39 +
27 override fun bind(viewBinding: ParticipantItemBinding, position: Int) { 40 override fun bind(viewBinding: ParticipantItemBinding, position: Int) {
28 - viewBinding.identityText.text = participant.identity 41 +
  42 + ensureCoroutineScope()
  43 + coroutineScope?.launch {
  44 + participant::identity.flow.collect { identity ->
  45 + viewBinding.identityText.text = identity
  46 + }
  47 + }
  48 + coroutineScope?.launch {
  49 + participant::audioTracks.flow
  50 + .flatMapLatest { tracks ->
  51 + val audioTrack = tracks.values.firstOrNull()
  52 + if (audioTrack != null) {
  53 + audioTrack::muted.flow
  54 + } else {
  55 + flowOf(true)
  56 + }
  57 + }
  58 + .collect { muted ->
  59 + viewBinding.muteIndicator.visibility = if (muted) View.VISIBLE else View.INVISIBLE
  60 + }
  61 + }
29 participant.listener = object : ParticipantListener { 62 participant.listener = object : ParticipantListener {
30 override fun onTrackSubscribed( 63 override fun onTrackSubscribed(
31 track: Track, 64 track: Track,
@@ -67,6 +100,8 @@ class ParticipantItem( @@ -67,6 +100,8 @@ class ParticipantItem(
67 } 100 }
68 101
69 override fun unbind(viewHolder: GroupieViewHolder<ParticipantItemBinding>) { 102 override fun unbind(viewHolder: GroupieViewHolder<ParticipantItemBinding>) {
  103 + coroutineScope?.cancel()
  104 + coroutineScope = null
70 super.unbind(viewHolder) 105 super.unbind(viewHolder)
71 boundVideoTrack?.removeRenderer(viewHolder.binding.renderer) 106 boundVideoTrack?.removeRenderer(viewHolder.binding.renderer)
72 boundVideoTrack = null 107 boundVideoTrack = null