[Calling][Bug] video not visible to remote participants on join (#508)

This commit is contained in:
Inderpal Singh Aulakh 2022-10-14 09:28:45 -07:00 коммит произвёл Mohtasim
Родитель 1ade027e84
Коммит d1d71cb262
3 изменённых файлов: 159 добавлений и 15 удалений

Просмотреть файл

@ -79,8 +79,11 @@ internal class SetupViewModel(
state.localParticipantState.videoStreamID,
state.permissionState,
)
joinCallButtonHolderViewModel.init(state.permissionState.audioPermissionState)
joinCallButtonHolderViewModel.init(
state.permissionState.audioPermissionState,
state.permissionState.cameraPermissionState,
state.localParticipantState.cameraState.operation
)
super.init(coroutineScope)
}
@ -113,7 +116,9 @@ internal class SetupViewModel(
)
joinCallButtonHolderViewModel.update(
state.permissionState.audioPermissionState,
state.callState
state.callState,
state.permissionState.cameraPermissionState,
state.localParticipantState.cameraState.operation
)
}
}

Просмотреть файл

@ -11,6 +11,7 @@ import com.azure.android.communication.ui.calling.redux.action.ErrorAction
import com.azure.android.communication.ui.calling.redux.state.CallingState
import com.azure.android.communication.ui.calling.redux.state.CallingStatus
import com.azure.android.communication.ui.calling.redux.state.PermissionStatus
import com.azure.android.communication.ui.calling.redux.state.CameraOperationalStatus
import com.azure.android.communication.ui.calling.redux.state.isDisconnected
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -29,15 +30,31 @@ internal class JoinCallButtonHolderViewModel(private val dispatch: (Action) -> U
disableJoinCallButtonFlow.value = true
}
fun init(audioPermissionState: PermissionStatus) {
fun init(
audioPermissionState: PermissionStatus,
cameraPermissionState: PermissionStatus,
cameraOperationalStatus: CameraOperationalStatus
) {
joinCallButtonEnabledFlow =
MutableStateFlow(audioPermissionState == PermissionStatus.GRANTED)
MutableStateFlow(
audioPermissionState == PermissionStatus.GRANTED &&
cameraPermissionState != PermissionStatus.UNKNOWN &&
cameraOperationalStatus != CameraOperationalStatus.PENDING
)
disableJoinCallButtonFlow.value = false
}
fun update(audioPermissionState: PermissionStatus, callingState: CallingState) {
fun update(
audioPermissionState: PermissionStatus,
callingState: CallingState,
cameraPermissionState: PermissionStatus,
cameraOperationalStatus: CameraOperationalStatus
) {
disableJoinCallButtonFlow.value = callingState.callingStatus != CallingStatus.NONE
joinCallButtonEnabledFlow.value = audioPermissionState == PermissionStatus.GRANTED
joinCallButtonEnabledFlow.value =
audioPermissionState == PermissionStatus.GRANTED &&
cameraPermissionState != PermissionStatus.UNKNOWN &&
cameraOperationalStatus != CameraOperationalStatus.PENDING
if (callingState.isDisconnected()) {
disableJoinCallButtonFlow.value = false
} else {

Просмотреть файл

@ -1,12 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.android.communication.ui.presentation.fragment.setup.components
import com.azure.android.communication.ui.calling.presentation.fragment.setup.components.JoinCallButtonHolderViewModel
import com.azure.android.communication.ui.calling.redux.AppStore
import com.azure.android.communication.ui.ACSBaseTestCoroutine
import com.azure.android.communication.ui.calling.redux.state.CallingState
import com.azure.android.communication.ui.calling.redux.state.CallingStatus
import com.azure.android.communication.ui.calling.redux.state.PermissionStatus
import com.azure.android.communication.ui.calling.redux.state.CameraOperationalStatus
import com.azure.android.communication.ui.calling.redux.state.ReduxState
import com.azure.android.communication.ui.ACSBaseTestCoroutine
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
@ -27,7 +31,11 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
val mockAppStore = mock<AppStore<ReduxState>> {}
val viewModel = JoinCallButtonHolderViewModel(mockAppStore::dispatch)
viewModel.init(PermissionStatus.DENIED)
viewModel.init(
PermissionStatus.DENIED,
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
val emitResult = mutableListOf<Boolean>()
@ -37,7 +45,12 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
}
// act
viewModel.update(PermissionStatus.GRANTED, CallingState(CallingStatus.NONE))
viewModel.update(
PermissionStatus.GRANTED,
CallingState(CallingStatus.NONE),
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
// assert
Assert.assertEquals(
@ -61,7 +74,11 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
val mockAppStore = mock<AppStore<ReduxState>> {}
val viewModel = JoinCallButtonHolderViewModel(mockAppStore::dispatch)
viewModel.init(PermissionStatus.GRANTED)
viewModel.init(
PermissionStatus.GRANTED,
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
val emitResult = mutableListOf<Boolean>()
@ -71,7 +88,12 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
}
// act
viewModel.update(PermissionStatus.DENIED, CallingState(CallingStatus.NONE))
viewModel.update(
PermissionStatus.DENIED,
CallingState(CallingStatus.NONE),
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
// assert
Assert.assertEquals(
@ -95,7 +117,11 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
val mockAppStore = mock<AppStore<ReduxState>> {}
val viewModel = JoinCallButtonHolderViewModel(mockAppStore::dispatch)
viewModel.init(PermissionStatus.GRANTED)
viewModel.init(
PermissionStatus.GRANTED,
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
val emitResult = mutableListOf<Boolean>()
@ -110,7 +136,12 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
Assert.assertEquals(false, emitResult[0])
// act
viewModel.update(PermissionStatus.GRANTED, CallingState(CallingStatus.CONNECTING))
viewModel.update(
PermissionStatus.GRANTED,
CallingState(CallingStatus.CONNECTING),
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
// assert
// Should have disabled during connecting
@ -118,12 +149,103 @@ internal class JoinCallButtonHolderViewModelUnitTest : ACSBaseTestCoroutine() {
Assert.assertEquals(true, emitResult[1])
// act
viewModel.update(PermissionStatus.GRANTED, CallingState(CallingStatus.NONE))
viewModel.update(
PermissionStatus.GRANTED,
CallingState(CallingStatus.NONE),
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
// assert
// no more emits yet
Assert.assertEquals(false, emitResult[2])
resultFlow.cancel()
}
@ExperimentalCoroutinesApi
@Test
fun joinCallButtonHolderViewModel_onUpdate_then_notifyButtonDisabled_when_cameraPermissionStateIsUnknown() =
runScopedTest {
// arrange
val mockAppStore = mock<AppStore<ReduxState>> {}
val viewModel = JoinCallButtonHolderViewModel(mockAppStore::dispatch)
viewModel.init(
PermissionStatus.GRANTED,
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
val emitResult = mutableListOf<Boolean>()
val resultFlow = launch {
viewModel.getJoinCallButtonEnabledFlow()
.toList(emitResult)
}
// act
viewModel.update(
PermissionStatus.GRANTED,
CallingState(CallingStatus.NONE),
PermissionStatus.UNKNOWN,
CameraOperationalStatus.ON
)
// assert
Assert.assertEquals(
true,
emitResult[0]
)
Assert.assertEquals(
false,
emitResult[1]
)
resultFlow.cancel()
}
@ExperimentalCoroutinesApi
@Test
fun joinCallButtonHolderViewModel_onUpdate_then_notifyButtonDisabled_when_cameraOperationStateIsPending() =
runScopedTest {
// arrange
val mockAppStore = mock<AppStore<ReduxState>> {}
val viewModel = JoinCallButtonHolderViewModel(mockAppStore::dispatch)
viewModel.init(
PermissionStatus.GRANTED,
PermissionStatus.GRANTED,
CameraOperationalStatus.ON
)
val emitResult = mutableListOf<Boolean>()
val resultFlow = launch {
viewModel.getJoinCallButtonEnabledFlow()
.toList(emitResult)
}
// act
viewModel.update(
PermissionStatus.GRANTED,
CallingState(CallingStatus.NONE),
PermissionStatus.UNKNOWN,
CameraOperationalStatus.PENDING
)
// assert
Assert.assertEquals(
true,
emitResult[0]
)
Assert.assertEquals(
false,
emitResult[1]
)
resultFlow.cancel()
}
}