feat: Default to camera muted when joining ongoing voice call

This commit is contained in:
Valere 2026-04-14 14:45:35 +02:00
parent d259eb6634
commit 83c4fa8278
6 changed files with 131 additions and 3 deletions

View file

@ -20,6 +20,8 @@ import io.element.android.features.call.api.CurrentCallService
import io.element.android.features.enterprise.api.SessionEnterpriseService
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.notification.CallIntent
import io.element.android.libraries.matrix.api.room.CallIntentConsensus
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.powerlevels.canCall
@ -57,8 +59,7 @@ class RoomCallStatePresenter(
canJoinCall = canJoinCall,
isUserInTheCall = isUserInTheCall,
isUserLocallyInTheCall = isUserLocallyInTheCall,
// TODO resolve intent while the call is ongoing
isAudioCall = false
isAudioCall = roomInfo.activeCallIntentConsensus.isAudio(),
)
else -> RoomCallState.StandBy(
canStartCall = canJoinCall,
@ -70,3 +71,12 @@ class RoomCallStatePresenter(
return callState
}
}
fun CallIntentConsensus.isAudio(): Boolean {
val intent = when (this) {
is CallIntentConsensus.Full -> callIntent
is CallIntentConsensus.Partial -> callIntent
is CallIntentConsensus.None -> return false
}
return intent == CallIntent.AUDIO
}

View file

@ -14,6 +14,8 @@ import io.element.android.features.call.api.CurrentCallService
import io.element.android.features.call.test.FakeCurrentCallService
import io.element.android.features.enterprise.test.FakeSessionEnterpriseService
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.libraries.matrix.api.notification.CallIntent
import io.element.android.libraries.matrix.api.room.CallIntentConsensus
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
@ -188,6 +190,100 @@ class RoomCallStatePresenterTest {
}
}
@Test
fun `present - active call with audio Intent`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
roomPermissions = roomPermissions(true),
).apply {
givenRoomInfo(
aRoomInfo(
hasRoomCall = true,
activeCallIntentConsensus = CallIntentConsensus.Full(CallIntent.AUDIO),
activeRoomCallParticipants = emptyList(),
)
)
}
)
val presenter = createRoomCallStatePresenter(
joinedRoom = room,
currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))),
)
presenter.test {
skipItems(1)
assertThat(awaitItem()).isEqualTo(
RoomCallState.OnGoing(
canJoinCall = true,
isAudioCall = true,
isUserInTheCall = false,
isUserLocallyInTheCall = true,
)
)
}
}
@Test
fun `present - active call with partial audio Intent`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
roomPermissions = roomPermissions(true),
).apply {
givenRoomInfo(
aRoomInfo(
hasRoomCall = true,
activeCallIntentConsensus = CallIntentConsensus.Partial(CallIntent.AUDIO, 1, 4),
)
)
}
)
val presenter = createRoomCallStatePresenter(
joinedRoom = room,
currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))),
)
presenter.test {
skipItems(1)
assertThat(awaitItem()).isEqualTo(
RoomCallState.OnGoing(
canJoinCall = true,
isAudioCall = true,
isUserInTheCall = false,
isUserLocallyInTheCall = true,
)
)
}
}
@Test
fun `present - active call with no intent defaults to Audio`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
roomPermissions = roomPermissions(true),
).apply {
givenRoomInfo(
aRoomInfo(
hasRoomCall = true,
activeCallIntentConsensus = CallIntentConsensus.None,
)
)
}
)
val presenter = createRoomCallStatePresenter(
joinedRoom = room,
currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))),
)
presenter.test {
skipItems(1)
assertThat(awaitItem()).isEqualTo(
RoomCallState.OnGoing(
canJoinCall = true,
isAudioCall = false,
isUserInTheCall = false,
isUserLocallyInTheCall = true,
)
)
}
}
@Test
fun `present - user leaves the call`() = runTest {
val room = FakeJoinedRoom(