[Calling][Feature] CSS - public API to retrieve CallId and UI (#507)
This commit is contained in:
Родитель
db0e0464c7
Коммит
2bb7339e54
|
@ -67,6 +67,7 @@ internal class TestCallingSDK(private val callEvents: CallEvents, coroutineConte
|
|||
CallingSDK {
|
||||
private val coroutineScope = CoroutineScope(coroutineContextProvider.Default)
|
||||
private var callingStateWrapperSharedFlow = MutableSharedFlow<CallingStateWrapper>()
|
||||
private var callIdStateFlow = MutableStateFlow<String?>(null)
|
||||
private var remoteParticipantsInfoModelSharedFlow =
|
||||
MutableSharedFlow<Map<String, ParticipantInfoModel>>()
|
||||
private var isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -194,6 +195,7 @@ internal class TestCallingSDK(private val callEvents: CallEvents, coroutineConte
|
|||
startCallCompletableFuture.complete(null)
|
||||
callStarted.compareAndSet(false, true)
|
||||
callingStateWrapperSharedFlow.emit(CallingStateWrapper(CallState.CONNECTED, 0, 0))
|
||||
callIdStateFlow.emit("callid")
|
||||
emitRemoteParticipantFlow()
|
||||
}
|
||||
return startCallCompletableFuture
|
||||
|
@ -245,6 +247,8 @@ internal class TestCallingSDK(private val callEvents: CallEvents, coroutineConte
|
|||
return callingStateWrapperSharedFlow
|
||||
}
|
||||
|
||||
override fun getCallIdStateFlow(): StateFlow<String?> = callIdStateFlow
|
||||
|
||||
override fun getRemoteParticipantInfoModelSharedFlow(): Flow<Map<String, ParticipantInfoModel>> {
|
||||
coroutineScope.launch {
|
||||
emitRemoteParticipantFlow()
|
||||
|
|
|
@ -10,6 +10,8 @@ import com.azure.android.communication.common.CommunicationIdentifier;
|
|||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration;
|
||||
import com.azure.android.communication.ui.calling.configuration.CallConfiguration;
|
||||
import com.azure.android.communication.ui.calling.configuration.CallType;
|
||||
import com.azure.android.communication.ui.calling.di.DependencyInjectionContainer;
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeDiagnosticsInfo;
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeGroupCallLocator;
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeJoinLocator;
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeLocalOptions;
|
||||
|
@ -20,9 +22,12 @@ import com.azure.android.communication.ui.calling.models.CallCompositeParticipan
|
|||
import com.azure.android.communication.ui.calling.models.CallCompositeSetParticipantViewDataResult;
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeTeamsMeetingLinkLocator;
|
||||
import com.azure.android.communication.ui.calling.presentation.CallCompositeActivity;
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManager;
|
||||
|
||||
import static com.azure.android.communication.ui.calling.models.CallCompositeDiagnosticsInfoExtensionsKt.buildCallCompositeDiagnosticsInfo;
|
||||
import static com.azure.android.communication.ui.calling.service.sdk.TypeConversionsKt.into;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +55,7 @@ public final class CallComposite {
|
|||
private static int instanceId = 0;
|
||||
|
||||
private final CallCompositeConfiguration configuration;
|
||||
private WeakReference<DependencyInjectionContainer> diContainer;
|
||||
|
||||
CallComposite(final CallCompositeConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
|
@ -202,6 +208,26 @@ public final class CallComposite {
|
|||
.setParticipantViewData(into(identifier), participantViewData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Call Composite Diagnostics information.
|
||||
*
|
||||
* @return {@link CallCompositeDiagnosticsInfo}
|
||||
*/
|
||||
public CallCompositeDiagnosticsInfo getDiagnosticsInfo() {
|
||||
final DiagnosticsManager diagnosticsManager = getDiagnosticsManger();
|
||||
return diagnosticsManager != null
|
||||
? diagnosticsManager.getDiagnosticsInfo()
|
||||
: buildCallCompositeDiagnosticsInfo();
|
||||
}
|
||||
|
||||
void setDependencyInjectionContainer(final DependencyInjectionContainer diContainer) {
|
||||
this.diContainer = new WeakReference<DependencyInjectionContainer>(diContainer);
|
||||
}
|
||||
|
||||
private DiagnosticsManager getDiagnosticsManger() {
|
||||
return diContainer != null ? diContainer.get().getDiagnosticsManager() : null;
|
||||
}
|
||||
|
||||
private void launchComposite(final Context context,
|
||||
final CallCompositeRemoteOptions remoteOptions,
|
||||
final CallCompositeLocalOptions localOptions,
|
||||
|
@ -231,7 +257,7 @@ public final class CallComposite {
|
|||
configuration.setCallCompositeLocalOptions(localOptions);
|
||||
}
|
||||
|
||||
CallCompositeConfiguration.Companion.putConfig(instanceId, configuration);
|
||||
CallCompositeInstanceManager.putCallComposite(instanceId, this);
|
||||
|
||||
final Intent intent = new Intent(context, CallCompositeActivity.class);
|
||||
intent.putExtra(CallCompositeActivity.KEY_INSTANCE_ID, instanceId++);
|
||||
|
@ -241,6 +267,10 @@ public final class CallComposite {
|
|||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
CallCompositeConfiguration getConfiguration() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
void launchTest(final Context context,
|
||||
final CallCompositeRemoteOptions remoteOptions,
|
||||
final CallCompositeLocalOptions localOptions) {
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.calling
|
||||
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.di.DependencyInjectionContainer
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
internal class CallCompositeInstanceManager {
|
||||
|
||||
/**
|
||||
* CallCompositeInstance Storage
|
||||
*
|
||||
* The configuration for the call requires callbacks, but these callbacks
|
||||
* can not be passed via intent (not primitive/serializable data).
|
||||
*
|
||||
* This is a storage container for CallComposite objects, it uses a weak reference
|
||||
* to prevent CallComposite from leaking Activities via it's callbacks.
|
||||
*/
|
||||
|
||||
companion object {
|
||||
private val instances = mutableMapOf<Int, CallComposite>()
|
||||
|
||||
/**
|
||||
* Store a Config by Instance ID
|
||||
*/
|
||||
@JvmStatic
|
||||
fun putCallComposite(id: Int, callComposite: CallComposite) {
|
||||
instances[id] = callComposite
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeCallComposite(id: Int) {
|
||||
instances.remove(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a config by it's ID
|
||||
* May return null if the Configuration becomes garbage collected
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getCallComposite(id: Int): CallComposite = instances[id]
|
||||
?: throw CallCompositeException(
|
||||
"This ID is not valid, and no entry exists in the map. Please file a bug, this is an error in the composite",
|
||||
IllegalStateException()
|
||||
)
|
||||
|
||||
/**
|
||||
* Check if CallComposite exists
|
||||
*/
|
||||
@JvmStatic
|
||||
fun hasCallComposite(id: Int): Boolean = instances.containsKey(id)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun CallComposite.getConfig(): CallCompositeConfiguration {
|
||||
return this.configuration
|
||||
}
|
||||
|
||||
internal fun CallComposite.setDependencyInjectionContainer(diContainer: DependencyInjectionContainer) {
|
||||
return this.setDependencyInjectionContainer(diContainer)
|
||||
}
|
|
@ -3,11 +3,9 @@
|
|||
|
||||
package com.azure.android.communication.ui.calling.configuration
|
||||
|
||||
import com.azure.android.communication.ui.calling.CallCompositeException
|
||||
import com.azure.android.communication.ui.calling.configuration.events.CallCompositeEventsHandler
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeLocalOptions
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeLocalizationOptions
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
internal class CallCompositeConfiguration {
|
||||
var themeConfig: Int? = null
|
||||
|
@ -15,41 +13,5 @@ internal class CallCompositeConfiguration {
|
|||
var callCompositeEventsHandler = CallCompositeEventsHandler()
|
||||
var callConfig: CallConfiguration? = null
|
||||
var callCompositeLocalOptions: CallCompositeLocalOptions? = null
|
||||
val remoteParticipantsConfiguration: RemoteParticipantsConfiguration =
|
||||
RemoteParticipantsConfiguration()
|
||||
|
||||
/*
|
||||
CallCompositeConfiguration Storage
|
||||
|
||||
The configuration for the call requires callbacks, but these callbacks
|
||||
can not be passed via intent (not primitive/serializable data).
|
||||
|
||||
This is a storage container for Configuration objects, it uses a weak reference
|
||||
to prevent CallCompositeConfiguration from leaking Activities via it's callbacks.
|
||||
*/
|
||||
companion object {
|
||||
private val configs: HashMap<Int, CallCompositeConfiguration> = HashMap()
|
||||
|
||||
// Store a Config by Instance ID
|
||||
//
|
||||
// Pass a null configuration to explicitly remove an instance
|
||||
fun putConfig(id: Int, configuration: CallCompositeConfiguration?) {
|
||||
if (configuration == null) {
|
||||
configs.remove(id)
|
||||
} else {
|
||||
configs[id] = configuration
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a config by it's ID
|
||||
// May return null if the Configuration becomes garbage collected
|
||||
fun getConfig(id: Int): CallCompositeConfiguration = configs[id]
|
||||
?: throw CallCompositeException(
|
||||
"This ID is not valid, and no entry exists in the map. Please file a bug, this is an error in the composite",
|
||||
IllegalStateException()
|
||||
)
|
||||
|
||||
// Check if config exists
|
||||
fun hasConfig(id: Int): Boolean = configs[id] != null
|
||||
}
|
||||
val remoteParticipantsConfiguration: RemoteParticipantsConfiguration = RemoteParticipantsConfiguration()
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package com.azure.android.communication.ui.calling.configuration
|
|||
import com.azure.android.communication.ui.calling.models.CallCompositeParticipantViewData
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeSetParticipantViewDataResult
|
||||
import com.azure.android.communication.ui.calling.service.sdk.CommunicationIdentifier
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
internal data class RemoteParticipantViewData(
|
||||
val identifier: CommunicationIdentifier,
|
||||
|
@ -18,17 +19,17 @@ internal interface RemoteParticipantsConfigurationHandler {
|
|||
}
|
||||
|
||||
internal class RemoteParticipantsConfiguration {
|
||||
private var handler: RemoteParticipantsConfigurationHandler? = null
|
||||
private var handler: WeakReference<RemoteParticipantsConfigurationHandler>? = null
|
||||
|
||||
fun setHandler(handler: RemoteParticipantsConfigurationHandler) {
|
||||
this.handler = handler
|
||||
this.handler = WeakReference<RemoteParticipantsConfigurationHandler>(handler)
|
||||
}
|
||||
|
||||
fun setParticipantViewData(
|
||||
identifier: CommunicationIdentifier,
|
||||
participantViewData: CallCompositeParticipantViewData,
|
||||
): CallCompositeSetParticipantViewDataResult {
|
||||
handler?.let {
|
||||
handler?.get()?.let {
|
||||
return@setParticipantViewData it.onSetParticipantViewData(
|
||||
RemoteParticipantViewData(identifier, participantViewData)
|
||||
)
|
||||
|
@ -37,6 +38,6 @@ internal class RemoteParticipantsConfiguration {
|
|||
}
|
||||
|
||||
fun removeParticipantViewData(identifier: String) {
|
||||
handler?.onRemoveParticipantViewData(identifier)
|
||||
handler?.get()?.onRemoveParticipantViewData(identifier)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
package com.azure.android.communication.ui.calling.di
|
||||
|
||||
import com.azure.android.communication.ui.calling.CallComposite
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.error.ErrorHandler
|
||||
import com.azure.android.communication.ui.calling.handlers.RemoteParticipantHandler
|
||||
|
@ -18,6 +19,7 @@ import com.azure.android.communication.ui.calling.presentation.navigation.Naviga
|
|||
import com.azure.android.communication.ui.calling.redux.Store
|
||||
import com.azure.android.communication.ui.calling.redux.middleware.handler.CallingMiddlewareActionHandler
|
||||
import com.azure.android.communication.ui.calling.redux.state.ReduxState
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManager
|
||||
import com.azure.android.communication.ui.calling.service.NotificationService
|
||||
|
||||
// Dependency Container for the Call Composite Activity
|
||||
|
@ -28,6 +30,8 @@ internal interface DependencyInjectionContainer {
|
|||
val appStore: Store<ReduxState>
|
||||
val callingMiddlewareActionHandler: CallingMiddlewareActionHandler
|
||||
|
||||
val callComposite: CallComposite
|
||||
|
||||
// Config
|
||||
val configuration: CallCompositeConfiguration
|
||||
val errorHandler: ErrorHandler
|
||||
|
@ -43,6 +47,7 @@ internal interface DependencyInjectionContainer {
|
|||
val notificationService: NotificationService
|
||||
val audioFocusManager: AudioFocusManager
|
||||
val networkManager: NetworkManager
|
||||
val diagnosticsManager: DiagnosticsManager
|
||||
|
||||
// UI
|
||||
val videoViewManager: VideoViewManager
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
package com.azure.android.communication.ui.calling.di
|
||||
|
||||
import android.content.Context
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.CallComposite
|
||||
import com.azure.android.communication.ui.calling.error.ErrorHandler
|
||||
import com.azure.android.communication.ui.calling.getConfig
|
||||
import com.azure.android.communication.ui.calling.handlers.RemoteParticipantHandler
|
||||
import com.azure.android.communication.ui.calling.logger.DefaultLogger
|
||||
import com.azure.android.communication.ui.calling.presentation.VideoStreamRendererFactory
|
||||
|
@ -42,6 +43,8 @@ import com.azure.android.communication.ui.calling.redux.reducer.Reducer
|
|||
import com.azure.android.communication.ui.calling.redux.state.AppReduxState
|
||||
import com.azure.android.communication.ui.calling.redux.state.ReduxState
|
||||
import com.azure.android.communication.ui.calling.service.CallingService
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManagerImpl
|
||||
import com.azure.android.communication.ui.calling.service.NotificationService
|
||||
import com.azure.android.communication.ui.calling.service.sdk.CallingSDK
|
||||
import com.azure.android.communication.ui.calling.service.sdk.CallingSDKEventHandler
|
||||
|
@ -50,15 +53,15 @@ import com.azure.android.communication.ui.calling.utilities.CoroutineContextProv
|
|||
|
||||
internal class DependencyInjectionContainerImpl(
|
||||
private val parentContext: Context,
|
||||
private val instanceId: Int,
|
||||
override val callComposite: CallComposite,
|
||||
private val customCallingSDK: CallingSDK?,
|
||||
private val customVideoStreamRendererFactory: VideoStreamRendererFactory?,
|
||||
private val customCoroutineContextProvider: CoroutineContextProvider?
|
||||
) : DependencyInjectionContainer {
|
||||
|
||||
//region Overrides
|
||||
// These getters are required by the interface
|
||||
override val configuration get() = CallCompositeConfiguration.getConfig(instanceId)
|
||||
override val configuration by lazy {
|
||||
callComposite.getConfig()
|
||||
}
|
||||
|
||||
override val navigationRouter by lazy {
|
||||
NavigationRouterImpl(appStore)
|
||||
|
@ -106,6 +109,11 @@ internal class DependencyInjectionContainerImpl(
|
|||
applicationContext,
|
||||
)
|
||||
}
|
||||
override val diagnosticsManager: DiagnosticsManager by lazy {
|
||||
DiagnosticsManagerImpl(
|
||||
appStore,
|
||||
)
|
||||
}
|
||||
|
||||
override val avatarViewManager by lazy {
|
||||
AvatarViewManager(
|
||||
|
@ -152,7 +160,7 @@ internal class DependencyInjectionContainerImpl(
|
|||
|
||||
//region Redux
|
||||
// Initial State
|
||||
private val initialState by lazy { AppReduxState(configuration.callConfig!!.displayName) }
|
||||
private val initialState by lazy { AppReduxState(configuration.callConfig?.displayName) }
|
||||
|
||||
// Reducers
|
||||
private val callStateReducer get() = CallStateReducerImpl()
|
||||
|
@ -196,9 +204,9 @@ internal class DependencyInjectionContainerImpl(
|
|||
private val callingSDKWrapper: CallingSDK by lazy {
|
||||
customCallingSDK
|
||||
?: CallingSDKWrapper(
|
||||
instanceId,
|
||||
applicationContext,
|
||||
callingSDKEventHandler,
|
||||
configuration.callConfig
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.calling.models;
|
||||
|
||||
/**
|
||||
* A Call Composite Diagnostics information.
|
||||
*/
|
||||
public final class CallCompositeDiagnosticsInfo {
|
||||
|
||||
private String lastKnownCallId;
|
||||
|
||||
CallCompositeDiagnosticsInfo() { }
|
||||
|
||||
/**
|
||||
* Set last known call id.
|
||||
* @param lastKnownCallId last known call id.
|
||||
* @return {@link CallCompositeDiagnosticsInfo}
|
||||
*/
|
||||
CallCompositeDiagnosticsInfo setLastKnownCallId(final String lastKnownCallId) {
|
||||
this.lastKnownCallId = lastKnownCallId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last known call id.
|
||||
* @return {@link String}
|
||||
*/
|
||||
public String getLastKnownCallId() {
|
||||
return lastKnownCallId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.calling.models
|
||||
|
||||
internal fun CallCompositeDiagnosticsInfo.setCallId(lastKnownCallId: String?) {
|
||||
this.lastKnownCallId = lastKnownCallId
|
||||
}
|
||||
|
||||
internal fun buildCallCompositeDiagnosticsInfo(): CallCompositeDiagnosticsInfo = CallCompositeDiagnosticsInfo()
|
|
@ -22,7 +22,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.azure.android.communication.ui.R
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.CallCompositeInstanceManager
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeSupportedLocale
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.CallingFragment
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.setup.SetupFragment
|
||||
|
@ -61,6 +61,7 @@ internal class CallCompositeActivity : AppCompatActivity() {
|
|||
private val callingMiddlewareActionHandler get() = container.callingMiddlewareActionHandler
|
||||
private val videoViewManager get() = container.videoViewManager
|
||||
private val instanceId get() = intent.getIntExtra(KEY_INSTANCE_ID, -1)
|
||||
private val diagnosticsService get() = container.diagnosticsManager
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -116,6 +117,7 @@ internal class CallCompositeActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
notificationService.start(lifecycleScope)
|
||||
diagnosticsService.start(lifecycleScope)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -139,12 +141,12 @@ internal class CallCompositeActivity : AppCompatActivity() {
|
|||
// Covers edge case where Android tries to recreate call activity after process death
|
||||
// (e.g. due to revoked permission).
|
||||
// If no configs are detected we can just exit without cleanup.
|
||||
if (CallCompositeConfiguration.hasConfig(instanceId)) {
|
||||
if (CallCompositeInstanceManager.hasCallComposite(instanceId)) {
|
||||
audioFocusManager.stop()
|
||||
audioSessionManager.onDestroy(this)
|
||||
if (isFinishing) {
|
||||
store.dispatch(CallingAction.CallEndRequested())
|
||||
CallCompositeConfiguration.putConfig(instanceId, null)
|
||||
CallCompositeInstanceManager.removeCallComposite(instanceId)
|
||||
}
|
||||
}
|
||||
super.onDestroy()
|
||||
|
|
|
@ -7,7 +7,7 @@ import android.app.Application
|
|||
import androidx.lifecycle.AndroidViewModel
|
||||
import com.azure.android.communication.ui.R
|
||||
import com.azure.android.communication.ui.calling.CallCompositeException
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.CallCompositeInstanceManager
|
||||
import com.azure.android.communication.ui.calling.di.DependencyInjectionContainer
|
||||
import com.azure.android.communication.ui.calling.di.DependencyInjectionContainerImpl
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.CallingViewModel
|
||||
|
@ -16,6 +16,7 @@ import com.azure.android.communication.ui.calling.presentation.fragment.factorie
|
|||
import com.azure.android.communication.ui.calling.presentation.fragment.factories.SetupViewModelFactory
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.setup.SetupViewModel
|
||||
import com.azure.android.communication.ui.calling.service.sdk.CallingSDK
|
||||
import com.azure.android.communication.ui.calling.setDependencyInjectionContainer
|
||||
import com.azure.android.communication.ui.calling.utilities.CoroutineContextProvider
|
||||
|
||||
import java.lang.IllegalArgumentException
|
||||
|
@ -42,7 +43,7 @@ internal class DependencyInjectionContainerHolder(
|
|||
// Instance ID to locate Configuration. -1 is invalid.
|
||||
var instanceId: Int = -1
|
||||
set(value) {
|
||||
if (!CallCompositeConfiguration.hasConfig(value)) {
|
||||
if (!CallCompositeInstanceManager.hasCallComposite(value)) {
|
||||
val exceptionMessage =
|
||||
"Configuration with instanceId:$value does not exist. $commonMessage"
|
||||
throw CallCompositeException(exceptionMessage, IllegalArgumentException(exceptionMessage))
|
||||
|
@ -57,14 +58,20 @@ internal class DependencyInjectionContainerHolder(
|
|||
throw CallCompositeException(exceptionMessage, IllegalStateException(exceptionMessage))
|
||||
}
|
||||
|
||||
val callComposite = CallCompositeInstanceManager.getCallComposite(instanceId)
|
||||
|
||||
// Generate a new instance
|
||||
DependencyInjectionContainerImpl(
|
||||
val container = DependencyInjectionContainerImpl(
|
||||
application,
|
||||
instanceId,
|
||||
callComposite,
|
||||
customCallingSDK,
|
||||
customVideoStreamRendererFactory,
|
||||
customCoroutineContextProvider
|
||||
)
|
||||
|
||||
callComposite.setDependencyInjectionContainer(container)
|
||||
|
||||
return@lazy container
|
||||
}
|
||||
|
||||
val setupViewModel by lazy {
|
||||
|
@ -80,7 +87,8 @@ internal class DependencyInjectionContainerHolder(
|
|||
CallingViewModelFactory(
|
||||
container.appStore,
|
||||
ParticipantGridCellViewModelFactory(),
|
||||
application.resources.getInteger(R.integer.azure_communication_ui_calling_max_remote_participants)
|
||||
application.resources.getInteger(R.integer.azure_communication_ui_calling_max_remote_participants),
|
||||
container.diagnosticsManager
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.azure.android.communication.ui.R
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.CallCompositeInstanceManager
|
||||
import com.azure.android.communication.ui.calling.presentation.DependencyInjectionContainerHolder
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.banner.BannerView
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.ControlBarView
|
||||
|
@ -29,6 +29,7 @@ import com.azure.android.communication.ui.calling.presentation.fragment.calling.
|
|||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.participant.grid.ParticipantGridView
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.participantlist.ParticipantListView
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.common.audiodevicelist.AudioDeviceListView
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.more.MoreCallOptionsListView
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.setup.components.ErrorInfoView
|
||||
import com.azure.android.communication.ui.calling.presentation.navigation.BackNavigation
|
||||
|
||||
|
@ -63,13 +64,14 @@ internal class CallingFragment :
|
|||
private lateinit var powerManager: PowerManager
|
||||
private lateinit var accessibilityManager: AccessibilityManager
|
||||
private lateinit var wakeLock: PowerManager.WakeLock
|
||||
private lateinit var moreCallOptionsListView: MoreCallOptionsListView
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
viewModel.init(viewLifecycleOwner.lifecycleScope)
|
||||
|
||||
confirmLeaveOverlayView =
|
||||
LeaveConfirmView(viewModel.getConfirmLeaveOverlayViewModel(), this.requireContext())
|
||||
LeaveConfirmView(viewModel.confirmLeaveOverlayViewModel, this.requireContext())
|
||||
confirmLeaveOverlayView.layoutDirection =
|
||||
activity?.window?.decorView?.layoutDirection ?: LayoutDirection.LOCALE
|
||||
confirmLeaveOverlayView.start(
|
||||
|
@ -77,17 +79,12 @@ internal class CallingFragment :
|
|||
)
|
||||
|
||||
controlBarView = view.findViewById(R.id.azure_communication_ui_call_call_buttons)
|
||||
controlBarView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getControlBarViewModel(),
|
||||
this::requestCallEnd,
|
||||
this::openAudioDeviceSelectionMenu
|
||||
)
|
||||
controlBarView.start(viewLifecycleOwner, viewModel.controlBarViewModel)
|
||||
|
||||
participantGridView =
|
||||
view.findViewById(R.id.azure_communication_ui_call_participant_container)
|
||||
participantGridView.start(
|
||||
viewModel.getParticipantGridViewModel(),
|
||||
viewModel.participantGridViewModel,
|
||||
videoViewManager,
|
||||
viewLifecycleOwner,
|
||||
this::switchFloatingHeader,
|
||||
|
@ -95,15 +92,15 @@ internal class CallingFragment :
|
|||
)
|
||||
|
||||
lobbyOverlay = view.findViewById(R.id.azure_communication_ui_call_lobby_overlay)
|
||||
lobbyOverlay.start(viewLifecycleOwner, viewModel.getLobbyOverlayViewModel())
|
||||
lobbyOverlay.start(viewLifecycleOwner, viewModel.lobbyOverlayViewModel)
|
||||
|
||||
holdOverlay = view.findViewById(R.id.azure_communication_ui_call_hold_overlay)
|
||||
holdOverlay.start(viewLifecycleOwner, viewModel.getHoldOverlayViewModel())
|
||||
holdOverlay.start(viewLifecycleOwner, viewModel.holdOverlayViewModel)
|
||||
|
||||
localParticipantView = view.findViewById(R.id.azure_communication_ui_call_local_user_view)
|
||||
localParticipantView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getLocalParticipantViewModel(),
|
||||
viewModel.localParticipantViewModel,
|
||||
videoViewManager,
|
||||
avatarViewManager,
|
||||
)
|
||||
|
@ -113,19 +110,19 @@ internal class CallingFragment :
|
|||
infoHeaderView = view.findViewById(R.id.azure_communication_ui_call_floating_header)
|
||||
infoHeaderView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getFloatingHeaderViewModel(),
|
||||
viewModel.floatingHeaderViewModel,
|
||||
this::displayParticipantList,
|
||||
accessibilityManager.isEnabled
|
||||
)
|
||||
|
||||
audioDeviceListView =
|
||||
AudioDeviceListView(viewModel.getAudioDeviceListViewModel(), this.requireContext())
|
||||
AudioDeviceListView(viewModel.audioDeviceListViewModel, this.requireContext())
|
||||
audioDeviceListView.layoutDirection =
|
||||
activity?.window?.decorView?.layoutDirection ?: LayoutDirection.LOCALE
|
||||
audioDeviceListView.start(viewLifecycleOwner)
|
||||
|
||||
participantListView = ParticipantListView(
|
||||
viewModel.getParticipantListViewModel(),
|
||||
viewModel.participantListViewModel,
|
||||
this.requireContext(),
|
||||
avatarViewManager,
|
||||
)
|
||||
|
@ -135,7 +132,7 @@ internal class CallingFragment :
|
|||
|
||||
bannerView = view.findViewById(R.id.azure_communication_ui_call_banner)
|
||||
bannerView.start(
|
||||
viewModel.getBannerViewModel(),
|
||||
viewModel.bannerViewModel,
|
||||
viewLifecycleOwner,
|
||||
)
|
||||
participantGridView.setOnClickListener {
|
||||
|
@ -143,7 +140,15 @@ internal class CallingFragment :
|
|||
}
|
||||
|
||||
errorInfoView = ErrorInfoView(view)
|
||||
errorInfoView.start(viewLifecycleOwner, viewModel.getErrorInfoViewModel())
|
||||
errorInfoView.start(viewLifecycleOwner, viewModel.errorInfoViewModel)
|
||||
|
||||
moreCallOptionsListView = MoreCallOptionsListView(
|
||||
this.requireContext(),
|
||||
viewModel.moreCallOptionsListViewModel
|
||||
)
|
||||
moreCallOptionsListView.layoutDirection =
|
||||
activity?.window?.decorView?.layoutDirection ?: LayoutDirection.LOCALE
|
||||
moreCallOptionsListView.start(viewLifecycleOwner)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -177,11 +182,11 @@ internal class CallingFragment :
|
|||
super.onDestroy()
|
||||
if (activity?.isChangingConfigurations == false) {
|
||||
if (this::participantGridView.isInitialized) participantGridView.stop()
|
||||
if (CallCompositeConfiguration.hasConfig(holder.instanceId)) {
|
||||
if (CallCompositeInstanceManager.hasCallComposite(holder.instanceId)) {
|
||||
// Covers edge case where Android tries to recreate call activity after process death
|
||||
// (e.g. due to revoked permission).
|
||||
// If no configs are detected we can just exit without cleanup.
|
||||
viewModel.getBannerViewModel().dismissBanner()
|
||||
viewModel.bannerViewModel.dismissBanner()
|
||||
}
|
||||
}
|
||||
if (this::localParticipantView.isInitialized) localParticipantView.stop()
|
||||
|
@ -190,6 +195,7 @@ internal class CallingFragment :
|
|||
if (this::confirmLeaveOverlayView.isInitialized) confirmLeaveOverlayView.stop()
|
||||
if (this::holdOverlay.isInitialized) holdOverlay.stop()
|
||||
if (this::errorInfoView.isInitialized) errorInfoView.stop()
|
||||
if (this::moreCallOptionsListView.isInitialized) moreCallOptionsListView.stop()
|
||||
}
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
|
||||
|
@ -215,9 +221,9 @@ internal class CallingFragment :
|
|||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
mapOf(
|
||||
LEAVE_CONFIRM_VIEW_KEY to viewModel.getConfirmLeaveOverlayViewModel().getShouldDisplayLeaveConfirmFlow(),
|
||||
AUDIO_DEVICE_LIST_VIEW_KEY to viewModel.getAudioDeviceListViewModel().displayAudioDeviceSelectionMenuStateFlow,
|
||||
PARTICIPANT_LIST_VIEW_KEY to viewModel.getParticipantListViewModel().getDisplayParticipantListStateFlow()
|
||||
LEAVE_CONFIRM_VIEW_KEY to viewModel.confirmLeaveOverlayViewModel.getShouldDisplayLeaveConfirmFlow(),
|
||||
AUDIO_DEVICE_LIST_VIEW_KEY to viewModel.audioDeviceListViewModel.displayAudioDeviceSelectionMenuStateFlow,
|
||||
PARTICIPANT_LIST_VIEW_KEY to viewModel.participantListViewModel.getDisplayParticipantListStateFlow()
|
||||
).forEach { (key, element) -> outState.putBoolean(key, element.value) }
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
@ -227,9 +233,9 @@ internal class CallingFragment :
|
|||
|
||||
savedInstanceState?.let {
|
||||
mapOf(
|
||||
LEAVE_CONFIRM_VIEW_KEY to viewModel.getConfirmLeaveOverlayViewModel()::requestExitConfirmation,
|
||||
AUDIO_DEVICE_LIST_VIEW_KEY to viewModel.getAudioDeviceListViewModel()::displayAudioDeviceSelectionMenu,
|
||||
PARTICIPANT_LIST_VIEW_KEY to viewModel.getParticipantListViewModel()::displayParticipantList
|
||||
LEAVE_CONFIRM_VIEW_KEY to viewModel.confirmLeaveOverlayViewModel::requestExitConfirmation,
|
||||
AUDIO_DEVICE_LIST_VIEW_KEY to viewModel.audioDeviceListViewModel::displayAudioDeviceSelectionMenu,
|
||||
PARTICIPANT_LIST_VIEW_KEY to viewModel.participantListViewModel::displayParticipantList
|
||||
).forEach { (key, showDialog) -> if (it.getBoolean(key)) showDialog() }
|
||||
}
|
||||
}
|
||||
|
@ -238,12 +244,8 @@ internal class CallingFragment :
|
|||
viewModel.requestCallEnd()
|
||||
}
|
||||
|
||||
private fun openAudioDeviceSelectionMenu() {
|
||||
viewModel.getAudioDeviceListViewModel().displayAudioDeviceSelectionMenu()
|
||||
}
|
||||
|
||||
private fun displayParticipantList() {
|
||||
viewModel.getParticipantListViewModel().displayParticipantList()
|
||||
viewModel.participantListViewModel.displayParticipantList()
|
||||
}
|
||||
|
||||
private fun switchFloatingHeader() {
|
||||
|
|
|
@ -4,16 +4,6 @@
|
|||
package com.azure.android.communication.ui.calling.presentation.fragment.calling
|
||||
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.BaseViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.banner.BannerViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.ControlBarViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.hangup.LeaveConfirmViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.header.InfoHeaderViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.hold.OnHoldOverlayViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.lobby.LobbyOverlayViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.localuser.LocalParticipantViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.participant.grid.ParticipantGridViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.participantlist.ParticipantListViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.common.audiodevicelist.AudioDeviceListViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.factories.CallingViewModelFactory
|
||||
import com.azure.android.communication.ui.calling.redux.Store
|
||||
import com.azure.android.communication.ui.calling.redux.state.CallingStatus
|
||||
|
@ -27,64 +17,18 @@ internal class CallingViewModel(
|
|||
) :
|
||||
BaseViewModel(store) {
|
||||
|
||||
private val participantGridViewModel =
|
||||
callingViewModelProvider.participantGridViewModel
|
||||
private val controlBarViewModel = callingViewModelProvider.controlBarViewModel
|
||||
private val confirmLeaveOverlayViewModel =
|
||||
callingViewModelProvider.confirmLeaveOverlayViewModel
|
||||
private val localParticipantViewModel =
|
||||
callingViewModelProvider.localParticipantViewModel
|
||||
private val floatingHeaderViewModel = callingViewModelProvider.floatingHeaderViewModel
|
||||
private val audioDeviceListViewModel =
|
||||
callingViewModelProvider.audioDeviceListViewModel
|
||||
private val participantListViewModel =
|
||||
callingViewModelProvider.participantListViewModel
|
||||
private val bannerViewModel = callingViewModelProvider.bannerViewModel
|
||||
private val lobbyOverlayViewModel = callingViewModelProvider.lobbyOverlayViewModel
|
||||
private val holdOverlayViewModel = callingViewModelProvider.onHoldOverlayViewModel
|
||||
private val errorInfoViewModel = callingViewModelProvider.snackBarViewModel
|
||||
|
||||
fun getLobbyOverlayViewModel(): LobbyOverlayViewModel {
|
||||
return lobbyOverlayViewModel
|
||||
}
|
||||
|
||||
fun getHoldOverlayViewModel(): OnHoldOverlayViewModel {
|
||||
return holdOverlayViewModel
|
||||
}
|
||||
|
||||
fun getParticipantGridViewModel(): ParticipantGridViewModel {
|
||||
return participantGridViewModel
|
||||
}
|
||||
|
||||
fun getAudioDeviceListViewModel(): AudioDeviceListViewModel {
|
||||
return audioDeviceListViewModel
|
||||
}
|
||||
|
||||
fun getControlBarViewModel(): ControlBarViewModel {
|
||||
return controlBarViewModel
|
||||
}
|
||||
|
||||
fun getConfirmLeaveOverlayViewModel(): LeaveConfirmViewModel {
|
||||
return confirmLeaveOverlayViewModel
|
||||
}
|
||||
|
||||
fun getLocalParticipantViewModel(): LocalParticipantViewModel {
|
||||
return localParticipantViewModel
|
||||
}
|
||||
|
||||
fun getFloatingHeaderViewModel(): InfoHeaderViewModel {
|
||||
return floatingHeaderViewModel
|
||||
}
|
||||
|
||||
fun getParticipantListViewModel(): ParticipantListViewModel {
|
||||
return participantListViewModel
|
||||
}
|
||||
|
||||
fun getBannerViewModel(): BannerViewModel {
|
||||
return bannerViewModel
|
||||
}
|
||||
|
||||
fun getErrorInfoViewModel() = errorInfoViewModel
|
||||
val moreCallOptionsListViewModel = callingViewModelProvider.moreCallOptionsListViewModel
|
||||
val participantGridViewModel = callingViewModelProvider.participantGridViewModel
|
||||
val controlBarViewModel = callingViewModelProvider.controlBarViewModel
|
||||
val confirmLeaveOverlayViewModel = callingViewModelProvider.confirmLeaveOverlayViewModel
|
||||
val localParticipantViewModel = callingViewModelProvider.localParticipantViewModel
|
||||
val floatingHeaderViewModel = callingViewModelProvider.floatingHeaderViewModel
|
||||
val audioDeviceListViewModel = callingViewModelProvider.audioDeviceListViewModel
|
||||
val participantListViewModel = callingViewModelProvider.participantListViewModel
|
||||
val bannerViewModel = callingViewModelProvider.bannerViewModel
|
||||
val lobbyOverlayViewModel = callingViewModelProvider.lobbyOverlayViewModel
|
||||
val holdOverlayViewModel = callingViewModelProvider.onHoldOverlayViewModel
|
||||
val errorInfoViewModel = callingViewModelProvider.snackBarViewModel
|
||||
|
||||
fun switchFloatingHeader() {
|
||||
floatingHeaderViewModel.switchFloatingHeader()
|
||||
|
@ -100,7 +44,10 @@ internal class CallingViewModel(
|
|||
controlBarViewModel.init(
|
||||
state.permissionState,
|
||||
state.localParticipantState.cameraState,
|
||||
state.localParticipantState.audioState
|
||||
state.localParticipantState.audioState,
|
||||
this::requestCallEnd,
|
||||
audioDeviceListViewModel::displayAudioDeviceSelectionMenu,
|
||||
moreCallOptionsListViewModel::display,
|
||||
)
|
||||
|
||||
localParticipantViewModel.init(
|
||||
|
|
|
@ -33,8 +33,7 @@ internal class ControlBarView : ConstraintLayout {
|
|||
private lateinit var cameraToggle: ImageButton
|
||||
private lateinit var micToggle: ImageButton
|
||||
private lateinit var callAudioDeviceButton: ImageButton
|
||||
private lateinit var requestCallEndCallback: () -> Unit
|
||||
private lateinit var openAudioDeviceSelectionMenuCallback: () -> Unit
|
||||
private lateinit var moreButton: ImageButton
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
|
@ -42,18 +41,16 @@ internal class ControlBarView : ConstraintLayout {
|
|||
cameraToggle = findViewById(R.id.azure_communication_ui_call_cameraToggle)
|
||||
micToggle = findViewById(R.id.azure_communication_ui_call_call_audio)
|
||||
callAudioDeviceButton = findViewById(R.id.azure_communication_ui_call_audio_device_button)
|
||||
moreButton = findViewById(R.id.azure_communication_ui_call_control_bar_more)
|
||||
|
||||
subscribeClickListener()
|
||||
}
|
||||
|
||||
fun start(
|
||||
viewLifecycleOwner: LifecycleOwner,
|
||||
viewModel: ControlBarViewModel,
|
||||
requestCallEnd: () -> Unit,
|
||||
openAudioDeviceSelectionMenu: () -> Unit,
|
||||
) {
|
||||
this.viewModel = viewModel
|
||||
this.requestCallEndCallback = requestCallEnd
|
||||
this.openAudioDeviceSelectionMenuCallback = openAudioDeviceSelectionMenu
|
||||
|
||||
setupAccessibility()
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
|
@ -200,7 +197,7 @@ internal class ControlBarView : ConstraintLayout {
|
|||
|
||||
private fun subscribeClickListener() {
|
||||
endCallButton.setOnClickListener {
|
||||
requestCallEndCallback()
|
||||
viewModel.requestCallEnd()
|
||||
}
|
||||
micToggle.setOnClickListener {
|
||||
if (micToggle.isSelected) {
|
||||
|
@ -217,7 +214,10 @@ internal class ControlBarView : ConstraintLayout {
|
|||
}
|
||||
}
|
||||
callAudioDeviceButton.setOnClickListener {
|
||||
openAudioDeviceSelectionMenuCallback()
|
||||
viewModel.openAudioDeviceSelectionMenu()
|
||||
}
|
||||
moreButton.setOnClickListener {
|
||||
viewModel.openMoreMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,17 @@ internal class ControlBarViewModel(private val dispatch: (Action) -> Unit) {
|
|||
private lateinit var audioDeviceSelectionStatusStateFlow: MutableStateFlow<AudioDeviceSelectionStatus>
|
||||
private lateinit var shouldEnableMicButtonStateFlow: MutableStateFlow<Boolean>
|
||||
private lateinit var onHoldCallStatusStateFlow: MutableStateFlow<Boolean>
|
||||
lateinit var requestCallEnd: () -> Unit
|
||||
lateinit var openAudioDeviceSelectionMenu: () -> Unit
|
||||
lateinit var openMoreMenu: () -> Unit
|
||||
|
||||
fun init(
|
||||
permissionState: PermissionState,
|
||||
cameraState: CameraState,
|
||||
audioState: AudioState,
|
||||
requestCallEndCallback: () -> Unit,
|
||||
openAudioDeviceSelectionMenuCallback: () -> Unit,
|
||||
openMoreMenuCallback: () -> Unit
|
||||
) {
|
||||
cameraStateFlow =
|
||||
MutableStateFlow(CameraModel(permissionState.cameraPermissionState, cameraState))
|
||||
|
@ -34,6 +40,9 @@ internal class ControlBarViewModel(private val dispatch: (Action) -> Unit) {
|
|||
shouldEnableMicButtonStateFlow =
|
||||
MutableStateFlow(shouldEnableMicButton(audioState))
|
||||
onHoldCallStatusStateFlow = MutableStateFlow(false)
|
||||
requestCallEnd = requestCallEndCallback
|
||||
openAudioDeviceSelectionMenu = openAudioDeviceSelectionMenuCallback
|
||||
openMoreMenu = openMoreMenuCallback
|
||||
}
|
||||
|
||||
fun update(
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.more
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.azure.android.communication.ui.R
|
||||
import com.azure.android.communication.ui.calling.utilities.BottomCellAdapter
|
||||
import com.azure.android.communication.ui.calling.utilities.BottomCellItem
|
||||
import com.microsoft.fluentui.drawer.DrawerDialog
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class MoreCallOptionsListView(
|
||||
context: Context,
|
||||
private val viewModel: MoreCallOptionsListViewModel
|
||||
) : RelativeLayout(context) {
|
||||
|
||||
private var recyclerView: RecyclerView
|
||||
private lateinit var menuDrawer: DrawerDialog
|
||||
private lateinit var bottomCellAdapter: BottomCellAdapter
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.azure_communication_ui_calling_listview, this)
|
||||
recyclerView = findViewById(R.id.bottom_drawer_table)
|
||||
this.setBackgroundResource(R.color.azure_communication_ui_calling_color_bottom_drawer_background)
|
||||
}
|
||||
|
||||
fun start(viewLifecycleOwner: LifecycleOwner) {
|
||||
initializeDrawer()
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.displayStateFlow.collect {
|
||||
if (it) {
|
||||
menuDrawer.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
bottomCellAdapter.setBottomCellItems(mutableListOf())
|
||||
recyclerView.layoutManager = null
|
||||
menuDrawer.dismiss()
|
||||
menuDrawer.dismissDialog()
|
||||
this.removeAllViews()
|
||||
}
|
||||
|
||||
private fun initializeDrawer() {
|
||||
menuDrawer = DrawerDialog(context, DrawerDialog.BehaviorType.BOTTOM)
|
||||
menuDrawer.setContentView(this)
|
||||
menuDrawer.setOnDismissListener {
|
||||
viewModel.close()
|
||||
}
|
||||
|
||||
bottomCellAdapter = BottomCellAdapter()
|
||||
bottomCellAdapter.setBottomCellItems(bottomCellItems)
|
||||
recyclerView.adapter = bottomCellAdapter
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
}
|
||||
|
||||
private val bottomCellItems: List<BottomCellItem>
|
||||
get() {
|
||||
val bottomCellItems = listOf(
|
||||
BottomCellItem(
|
||||
icon = ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.azure_communication_ui_calling_ic_fluent_share_android_24_regular
|
||||
),
|
||||
title = context.getString(R.string.azure_communication_ui_calling_view_share_diagnostics),
|
||||
contentDescription = null,
|
||||
accessoryImage = null,
|
||||
accessoryColor = null,
|
||||
accessoryImageDescription = context.getString(R.string.azure_communication_ui_calling_view_share_diagnostics),
|
||||
enabled = false,
|
||||
participantViewData = null,
|
||||
isOnHold = false,
|
||||
) {
|
||||
menuDrawer.dismiss()
|
||||
shareDiagnosticsInfo()
|
||||
},
|
||||
)
|
||||
|
||||
return bottomCellItems
|
||||
}
|
||||
|
||||
private fun shareDiagnosticsInfo() {
|
||||
val share = Intent.createChooser(
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
putExtra(Intent.EXTRA_TEXT, viewModel.callId)
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TITLE, context.getString(R.string.azure_communication_ui_calling_view_share_diagnostics_title))
|
||||
},
|
||||
null
|
||||
)
|
||||
context.startActivity(share)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.more
|
||||
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManager
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
internal class MoreCallOptionsListViewModel(
|
||||
private val diagnosticsManager: DiagnosticsManager
|
||||
) {
|
||||
private val unknown = "UNKNOWN"
|
||||
val callId: String
|
||||
get() {
|
||||
val lastKnownCallId = diagnosticsManager.diagnosticsInfo.lastKnownCallId
|
||||
return "Call ID: \"${if (lastKnownCallId.isNullOrEmpty()) unknown else lastKnownCallId}\""
|
||||
}
|
||||
|
||||
val displayStateFlow = MutableStateFlow(false)
|
||||
|
||||
fun display() {
|
||||
displayStateFlow.value = true
|
||||
}
|
||||
|
||||
fun close() {
|
||||
displayStateFlow.value = false
|
||||
}
|
||||
}
|
|
@ -13,7 +13,9 @@ import com.azure.android.communication.ui.calling.presentation.fragment.calling.
|
|||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.participant.grid.ParticipantGridViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.participantlist.ParticipantListViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.common.audiodevicelist.AudioDeviceListViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.more.MoreCallOptionsListViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.setup.components.ErrorInfoViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManager
|
||||
import com.azure.android.communication.ui.calling.redux.Store
|
||||
import com.azure.android.communication.ui.calling.redux.state.ReduxState
|
||||
|
||||
|
@ -21,8 +23,13 @@ internal class CallingViewModelFactory(
|
|||
private val store: Store<ReduxState>,
|
||||
private val participantGridCellViewModelFactory: ParticipantGridCellViewModelFactory,
|
||||
private val maxRemoteParticipants: Int,
|
||||
private val diagnosticsManager: DiagnosticsManager
|
||||
) {
|
||||
|
||||
val moreCallOptionsListViewModel by lazy {
|
||||
MoreCallOptionsListViewModel(diagnosticsManager)
|
||||
}
|
||||
|
||||
val participantGridViewModel by lazy {
|
||||
ParticipantGridViewModel(participantGridCellViewModelFactory, maxRemoteParticipants)
|
||||
}
|
||||
|
|
|
@ -55,39 +55,39 @@ internal class SetupFragment :
|
|||
setActionBarTitle()
|
||||
|
||||
setupGradientView = view.findViewById(R.id.azure_communication_ui_setup_gradient)
|
||||
setupGradientView.start(viewLifecycleOwner, viewModel.getSetupGradientViewViewModel())
|
||||
setupGradientView.start(viewLifecycleOwner, viewModel.setupGradientViewModel)
|
||||
|
||||
setupJoinCallButtonHolderView =
|
||||
view.findViewById(R.id.azure_communication_ui_setup_join_call_holder)
|
||||
setupJoinCallButtonHolderView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getJoinCallButtonHolderViewModel(),
|
||||
viewModel.joinCallButtonHolderViewModel,
|
||||
networkManager
|
||||
)
|
||||
|
||||
participantAvatarView = view.findViewById(R.id.azure_communication_ui_setup_default_avatar)
|
||||
participantAvatarView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getParticipantAvatarViewModel(),
|
||||
viewModel.participantAvatarViewModel,
|
||||
avatarViewManager.callCompositeLocalOptions?.participantViewData,
|
||||
)
|
||||
|
||||
warningsView = view.findViewById(R.id.azure_communication_ui_setup_permission_info)
|
||||
warningsView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getWarningsViewModel(),
|
||||
viewModel.warningsViewModel,
|
||||
)
|
||||
|
||||
localParticipantRendererView =
|
||||
view.findViewById(R.id.azure_communication_ui_setup_local_video_holder)
|
||||
localParticipantRendererView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getLocalParticipantRendererViewModel(),
|
||||
viewModel.localParticipantRendererViewModel,
|
||||
videoViewManager,
|
||||
)
|
||||
|
||||
audioDeviceListView =
|
||||
AudioDeviceListView(viewModel.getAudioDeviceListViewModel(), this.requireContext())
|
||||
AudioDeviceListView(viewModel.audioDeviceListViewModel, this.requireContext())
|
||||
audioDeviceListView.layoutDirection =
|
||||
activity?.window?.decorView?.layoutDirection ?: LayoutDirection.LOCALE
|
||||
audioDeviceListView.start(viewLifecycleOwner)
|
||||
|
@ -95,11 +95,11 @@ internal class SetupFragment :
|
|||
setupControlsView = view.findViewById(R.id.azure_communication_ui_setup_buttons)
|
||||
setupControlsView.start(
|
||||
viewLifecycleOwner,
|
||||
viewModel.getSetupControlsViewModel()
|
||||
viewModel.setupControlsViewModel,
|
||||
)
|
||||
|
||||
errorInfoView = ErrorInfoView(view)
|
||||
errorInfoView.start(viewLifecycleOwner, viewModel.getErrorInfoViewModel())
|
||||
errorInfoView.start(viewLifecycleOwner, viewModel.errorInfoViewModel)
|
||||
|
||||
viewModel.setupCall()
|
||||
}
|
||||
|
|
|
@ -17,30 +17,14 @@ internal class SetupViewModel(
|
|||
) :
|
||||
BaseViewModel(store) {
|
||||
|
||||
private val warningsViewModel = setupViewModelProvider.warningsViewModel
|
||||
private val setupControlsViewModel = setupViewModelProvider.setupControlsViewModel
|
||||
private val localParticipantRendererViewModel = setupViewModelProvider.previewAreaViewModel
|
||||
private val audioDeviceListViewModel = setupViewModelProvider.audioDeviceListViewModel
|
||||
private val errorInfoViewModel = setupViewModelProvider.snackBarViewModel
|
||||
private val setupGradientViewModel = setupViewModelProvider.setupGradientViewModel
|
||||
private val participantAvatarViewModel = setupViewModelProvider.participantAvatarViewModel
|
||||
private val joinCallButtonHolderViewModel = setupViewModelProvider.joinCallButtonHolderViewModel
|
||||
|
||||
fun getJoinCallButtonHolderViewModel() = joinCallButtonHolderViewModel
|
||||
|
||||
fun getParticipantAvatarViewModel() = participantAvatarViewModel
|
||||
|
||||
fun getSetupGradientViewViewModel() = setupGradientViewModel
|
||||
|
||||
fun getErrorInfoViewModel() = errorInfoViewModel
|
||||
|
||||
fun getLocalParticipantRendererViewModel() = localParticipantRendererViewModel
|
||||
|
||||
fun getAudioDeviceListViewModel() = audioDeviceListViewModel
|
||||
|
||||
fun getWarningsViewModel() = warningsViewModel
|
||||
|
||||
fun getSetupControlsViewModel() = setupControlsViewModel
|
||||
val warningsViewModel = setupViewModelProvider.warningsViewModel
|
||||
val setupControlsViewModel = setupViewModelProvider.setupControlsViewModel
|
||||
val localParticipantRendererViewModel = setupViewModelProvider.previewAreaViewModel
|
||||
val audioDeviceListViewModel = setupViewModelProvider.audioDeviceListViewModel
|
||||
val errorInfoViewModel = setupViewModelProvider.snackBarViewModel
|
||||
val setupGradientViewModel = setupViewModelProvider.setupGradientViewModel
|
||||
val participantAvatarViewModel = setupViewModelProvider.participantAvatarViewModel
|
||||
val joinCallButtonHolderViewModel = setupViewModelProvider.joinCallButtonHolderViewModel
|
||||
|
||||
val displayName: String?
|
||||
get() = store.getCurrentState().localParticipantState.displayName
|
||||
|
@ -56,7 +40,7 @@ internal class SetupViewModel(
|
|||
|
||||
override fun init(coroutineScope: CoroutineScope) {
|
||||
val state = store.getCurrentState()
|
||||
getWarningsViewModel().init(state.permissionState)
|
||||
warningsViewModel.init(state.permissionState)
|
||||
localParticipantRendererViewModel.init(
|
||||
state.localParticipantState.videoStreamID,
|
||||
)
|
||||
|
@ -95,7 +79,7 @@ internal class SetupViewModel(
|
|||
state.localParticipantState.audioState,
|
||||
state.callState,
|
||||
)
|
||||
getWarningsViewModel().update(state.permissionState)
|
||||
warningsViewModel.update(state.permissionState)
|
||||
localParticipantRendererViewModel.update(
|
||||
state.localParticipantState.videoStreamID,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.calling.presentation.manager
|
||||
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeDiagnosticsInfo
|
||||
import com.azure.android.communication.ui.calling.models.buildCallCompositeDiagnosticsInfo
|
||||
import com.azure.android.communication.ui.calling.models.setCallId
|
||||
import com.azure.android.communication.ui.calling.redux.Store
|
||||
import com.azure.android.communication.ui.calling.redux.state.ReduxState
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal interface DiagnosticsManager {
|
||||
fun start(coroutineScope: CoroutineScope)
|
||||
val diagnosticsInfo: CallCompositeDiagnosticsInfo
|
||||
}
|
||||
|
||||
internal class DiagnosticsManagerImpl(
|
||||
private val store: Store<ReduxState>,
|
||||
) : DiagnosticsManager {
|
||||
|
||||
override var diagnosticsInfo = buildCallCompositeDiagnosticsInfo()
|
||||
|
||||
override fun start(coroutineScope: CoroutineScope) {
|
||||
coroutineScope.launch {
|
||||
store.getStateFlow().collect {
|
||||
if (!it.callState.callId.isNullOrEmpty()) {
|
||||
val newDiagnosticsInfo = buildCallCompositeDiagnosticsInfo()
|
||||
newDiagnosticsInfo.setCallId(it.callState.callId)
|
||||
diagnosticsInfo = newDiagnosticsInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,4 +14,5 @@ internal sealed class CallingAction : Action {
|
|||
class StateUpdated(val callingState: CallingStatus) : CallingAction()
|
||||
class IsRecordingUpdated(val isRecording: Boolean) : CallingAction()
|
||||
class IsTranscribingUpdated(val isTranscribing: Boolean) : CallingAction()
|
||||
class CallIdUpdated(val callId: String?) : CallingAction()
|
||||
}
|
||||
|
|
|
@ -206,6 +206,7 @@ internal class CallingMiddlewareActionHandlerImpl(
|
|||
subscribeIsRecordingUpdate(store)
|
||||
subscribeIsTranscribingUpdate(store)
|
||||
subscribeCallInfoModelEventUpdate(store)
|
||||
subscribeCallIdUpdate(store)
|
||||
subscribeCamerasCountUpdate(store)
|
||||
|
||||
callingService.startCall(
|
||||
|
@ -390,6 +391,14 @@ internal class CallingMiddlewareActionHandlerImpl(
|
|||
}
|
||||
}
|
||||
|
||||
private fun subscribeCallIdUpdate(store: Store<ReduxState>) {
|
||||
coroutineScope.launch {
|
||||
callingService.getCallIdStateFlow().collect {
|
||||
store.dispatch(CallingAction.CallIdUpdated(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryCameraOn(store: Store<ReduxState>) {
|
||||
val state = store.getCurrentState()
|
||||
if (state.localParticipantState.cameraState.operation == CameraOperationalStatus.PAUSED) {
|
||||
|
|
|
@ -24,6 +24,9 @@ internal class CallStateReducerImpl : CallStateReducer {
|
|||
is CallingAction.CallStartRequested -> {
|
||||
callingState.copy(joinCallIsRequested = true)
|
||||
}
|
||||
is CallingAction.CallIdUpdated -> {
|
||||
callingState.copy(callId = action.callId)
|
||||
}
|
||||
else -> callingState
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ internal enum class CallingStatus {
|
|||
|
||||
internal data class CallingState(
|
||||
val callingStatus: CallingStatus,
|
||||
var callId: String? = null,
|
||||
// due to the async nature of the CallingStatus update we need to indicate joining call
|
||||
// until we receive CallingStatus.CONNECTING from the SDK.
|
||||
val joinCallIsRequested: Boolean = false,
|
||||
|
|
|
@ -18,6 +18,7 @@ import kotlinx.coroutines.cancel
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -37,6 +38,7 @@ internal class CallingService(
|
|||
private val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
private val coroutineScope = CoroutineScope((coroutineContextProvider.Default))
|
||||
private var callInfoModelSharedFlow = MutableSharedFlow<CallInfoModel>()
|
||||
private var callIdStateFlow = MutableStateFlow<String?>(null)
|
||||
private var callingStatus: CallingStatus = CallingStatus.NONE
|
||||
|
||||
fun turnCameraOn(): CompletableFuture<String> {
|
||||
|
@ -86,6 +88,8 @@ internal class CallingService(
|
|||
|
||||
fun getCallInfoModelEventSharedFlow(): SharedFlow<CallInfoModel> = callInfoModelSharedFlow
|
||||
|
||||
fun getCallIdStateFlow(): SharedFlow<String?> = callIdStateFlow
|
||||
|
||||
fun getIsTranscribingSharedFlow(): Flow<Boolean> {
|
||||
return isTranscribingSharedFlow
|
||||
}
|
||||
|
@ -123,6 +127,12 @@ internal class CallingService(
|
|||
}
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
callingSdk.getCallIdStateFlow().collect {
|
||||
callIdStateFlow.emit(it)
|
||||
}
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
callingSdk.getIsMutedSharedFlow().collect {
|
||||
isMutedSharedFlow.emit(it)
|
||||
|
|
|
@ -46,6 +46,7 @@ internal interface CallingSDK {
|
|||
fun getIsRecordingSharedFlow(): SharedFlow<Boolean>
|
||||
fun getIsMutedSharedFlow(): SharedFlow<Boolean>
|
||||
fun getCallingStateWrapperSharedFlow(): SharedFlow<CallingStateWrapper>
|
||||
fun getCallIdStateFlow(): StateFlow<String?>
|
||||
fun getRemoteParticipantInfoModelSharedFlow(): Flow<Map<String, ParticipantInfoModel>>
|
||||
fun getCamerasCountStateFlow(): StateFlow<Int>
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ import kotlinx.coroutines.FlowPreview
|
|||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -38,6 +40,7 @@ internal class CallingSDKEventHandler(
|
|||
private var isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
private var isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
private var callingStateWrapperSharedFlow = MutableSharedFlow<CallingStateWrapper>()
|
||||
private var callIdSharedFlow = MutableStateFlow<String?>(null)
|
||||
private var remoteParticipantsInfoModelSharedFlow =
|
||||
MutableSharedFlow<Map<String, ParticipantInfoModel>>()
|
||||
|
||||
|
@ -59,6 +62,8 @@ internal class CallingSDKEventHandler(
|
|||
fun getCallingStateWrapperSharedFlow(): SharedFlow<CallingStateWrapper> =
|
||||
callingStateWrapperSharedFlow
|
||||
|
||||
fun getCallIdStateFlow(): StateFlow<String?> = callIdSharedFlow
|
||||
|
||||
fun getIsMutedSharedFlow(): SharedFlow<Boolean> = isMutedSharedFlow
|
||||
|
||||
fun getIsRecordingSharedFlow(): SharedFlow<Boolean> = isRecordingSharedFlow
|
||||
|
@ -132,6 +137,10 @@ internal class CallingSDKEventHandler(
|
|||
}
|
||||
|
||||
private fun onCallStateChange() {
|
||||
coroutineScope.launch {
|
||||
callIdSharedFlow.emit(call?.id)
|
||||
}
|
||||
|
||||
val callState = call?.state
|
||||
var callEndStatus = Pair(0, 0)
|
||||
|
||||
|
@ -337,6 +346,7 @@ internal class CallingSDKEventHandler(
|
|||
isRecordingSharedFlow = MutableSharedFlow()
|
||||
isTranscribingSharedFlow = MutableSharedFlow()
|
||||
callingStateWrapperSharedFlow = MutableSharedFlow()
|
||||
callIdSharedFlow = MutableStateFlow(null)
|
||||
remoteParticipantsInfoModelSharedFlow = MutableSharedFlow()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.azure.android.communication.calling.TeamsMeetingLinkLocator
|
|||
import com.azure.android.communication.calling.VideoDevicesUpdatedListener
|
||||
import com.azure.android.communication.calling.VideoOptions
|
||||
import com.azure.android.communication.ui.calling.CallCompositeException
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import com.azure.android.communication.ui.calling.configuration.CallConfiguration
|
||||
import com.azure.android.communication.ui.calling.configuration.CallType
|
||||
import com.azure.android.communication.ui.calling.logger.Logger
|
||||
|
@ -35,11 +34,12 @@ import com.azure.android.communication.ui.calling.service.sdk.ext.setTags
|
|||
import java9.util.concurrent.CompletableFuture
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
internal class CallingSDKWrapper(
|
||||
private val instanceId: Int,
|
||||
private val context: Context,
|
||||
private val callingSDKEventHandler: CallingSDKEventHandler,
|
||||
private val callConfigInjected: CallConfiguration?,
|
||||
private val logger: Logger? = null,
|
||||
) : CallingSDK {
|
||||
private var nullableCall: Call? = null
|
||||
|
@ -52,14 +52,13 @@ internal class CallingSDKWrapper(
|
|||
private var camerasInitializedCompletableFuture: CompletableFuture<Void>? = null
|
||||
private var setupCallCompletableFuture: CompletableFuture<Void> = CompletableFuture()
|
||||
|
||||
private val configuration get() = CallCompositeConfiguration.getConfig(instanceId)
|
||||
private var videoDevicesUpdatedListener: VideoDevicesUpdatedListener? = null
|
||||
private var camerasCountStateFlow = MutableStateFlow(0)
|
||||
|
||||
private val callConfig: CallConfiguration
|
||||
get() {
|
||||
try {
|
||||
return configuration.callConfig!!
|
||||
return callConfigInjected!!
|
||||
} catch (ex: Exception) {
|
||||
throw CallCompositeException(
|
||||
"Call configurations are not set",
|
||||
|
@ -91,6 +90,8 @@ internal class CallingSDKWrapper(
|
|||
override fun getCallingStateWrapperSharedFlow() =
|
||||
callingSDKEventHandler.getCallingStateWrapperSharedFlow()
|
||||
|
||||
override fun getCallIdStateFlow(): StateFlow<String?> = callingSDKEventHandler.getCallIdStateFlow()
|
||||
|
||||
override fun getIsMutedSharedFlow() = callingSDKEventHandler.getIsMutedSharedFlow()
|
||||
|
||||
override fun getIsRecordingSharedFlow() = callingSDKEventHandler.getIsRecordingSharedFlow()
|
||||
|
@ -150,7 +151,7 @@ internal class CallingSDKWrapper(
|
|||
override fun setupCall(): CompletableFuture<Void> {
|
||||
if (callClient == null) {
|
||||
val callClientOptions = CallClientOptions().also {
|
||||
it.setTags(configuration.callConfig?.diagnosticConfig?.tags, logger)
|
||||
it.setTags(callConfig.diagnosticConfig.tags, logger)
|
||||
}
|
||||
callClient = CallClient(callClientOptions)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
>
|
||||
<path
|
||||
android:fillColor="@color/azure_communication_ui_calling_color_on_surface"
|
||||
android:pathData="M17 2.498c1.934 0 3.502 1.568 3.502 3.502 0 1.934-1.568 3.502-3.502 3.502-1.03 0-1.956-0.445-2.597-1.153l-4.558 2.604c0.103 0.33 0.159 0.682 0.159 1.047 0 0.364-0.056 0.716-0.16 1.046l4.558 2.606c0.641-0.709 1.568-1.154 2.598-1.154 1.934 0 3.502 1.568 3.502 3.502 0 1.934-1.568 3.502-3.502 3.502-1.934 0-3.502-1.568-3.502-3.502 0-0.365 0.056-0.716 0.16-1.047L9.1 14.348c-0.641 0.708-1.568 1.154-2.598 1.154C4.568 15.502 3 13.934 3 12c0-1.934 1.568-3.502 3.502-3.502 1.03 0 1.956 0.445 2.597 1.152l4.558-2.604C13.554 6.716 13.498 6.364 13.498 6c0-1.934 1.568-3.502 3.502-3.502zm0 13.5c-1.105 0-2.002 0.896-2.002 2.002 0 1.105 0.897 2.002 2.002 2.002 1.105 0 2.002-0.897 2.002-2.002 0-1.106-0.896-2.002-2.002-2.002zm-10.498-6C5.396 9.998 4.5 10.894 4.5 12c0 1.105 0.896 2.002 2.002 2.002 1.105 0 2.002-0.897 2.002-2.002 0-1.106-0.897-2.002-2.002-2.002zm10.498-6c-1.105 0-2.002 0.896-2.002 2.002 0 1.105 0.897 2.002 2.002 2.002 1.105 0 2.002-0.897 2.002-2.002 0-1.106-0.896-2.002-2.002-2.002z"
|
||||
/>
|
||||
</vector>
|
|
@ -17,18 +17,34 @@
|
|||
style="@style/Widget.FluentUI.Button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_audio_device_button"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_control_bar_more"
|
||||
android:background="@drawable/azure_communication_ui_calling_corner_radius_rectangle_4dp"
|
||||
android:backgroundTint="@color/azure_communication_ui_calling_color_background_red"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_button_hang_up_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_call_end_28_filled_composite_button_filled"
|
||||
app:layout_constraintBottom_toTopOf="@+id/azure_communication_ui_call_audio_device_button"
|
||||
app:layout_constraintBottom_toTopOf="@+id/azure_communication_ui_call_control_bar_more"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="spread_inside"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/azure_communication_ui_call_control_bar_more"
|
||||
style="@style/Widget.FluentUI.Button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_audio_device_button"
|
||||
android:background="@color/azure_communication_ui_calling_color_button_background_transparent"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_more_menu_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_dot_button_22_composite_button_filled"
|
||||
app:layout_constraintBottom_toTopOf="@+id/azure_communication_ui_call_audio_device_button"
|
||||
app:layout_constraintTop_toBottomOf="@+id/azure_communication_ui_call_end_call_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
/>
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/azure_communication_ui_call_audio_device_button"
|
||||
style="@style/Widget.FluentUI.Button"
|
||||
|
@ -39,7 +55,7 @@
|
|||
android:contentDescription="@string/azure_communication_ui_calling_view_button_device_options_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_speaker_2_24_regular_composite_button_filled"
|
||||
app:layout_constraintBottom_toTopOf="@+id/azure_communication_ui_call_call_audio"
|
||||
app:layout_constraintTop_toBottomOf="@+id/azure_communication_ui_call_end_call_button"
|
||||
app:layout_constraintTop_toBottomOf="@+id/azure_communication_ui_call_control_bar_more"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
/>
|
||||
|
|
|
@ -51,26 +51,42 @@
|
|||
android:background="@color/azure_communication_ui_calling_color_button_background_transparent"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_button_device_options_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_speaker_2_24_regular_composite_button_filled"
|
||||
app:layout_constraintEnd_toStartOf="@+id/azure_communication_ui_call_end_call_button"
|
||||
app:layout_constraintEnd_toStartOf="@+id/azure_communication_ui_call_control_bar_more"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_call_audio"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/azure_communication_ui_call_control_bar_more"
|
||||
style="@style/Widget.FluentUI.Button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_audio_device_button"
|
||||
android:background="@color/azure_communication_ui_calling_color_button_background_transparent"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_more_menu_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_dot_button_22_composite_button_filled"
|
||||
app:layout_constraintEnd_toStartOf="@+id/azure_communication_ui_call_end_call_button"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_audio_device_button"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/azure_communication_ui_call_end_call_button"
|
||||
style="@style/Widget.FluentUI.Button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_audio_device_button"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_control_bar_more"
|
||||
android:background="@drawable/azure_communication_ui_calling_corner_radius_rectangle_4dp"
|
||||
android:backgroundTint="@color/azure_communication_ui_calling_color_background_red"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_button_hang_up_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_call_end_28_filled_composite_button_filled"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_audio_device_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_control_bar_more"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
|
|
@ -47,13 +47,29 @@
|
|||
android:background="@color/azure_communication_ui_calling_color_button_background_transparent"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_button_device_options_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_speaker_2_24_regular_composite_button_filled"
|
||||
app:layout_constraintEnd_toStartOf="@+id/azure_communication_ui_call_end_call_button"
|
||||
app:layout_constraintEnd_toStartOf="@+id/azure_communication_ui_call_control_bar_more"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_call_audio"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/azure_communication_ui_call_control_bar_more"
|
||||
style="@style/Widget.FluentUI.Button"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:accessibilityTraversalAfter="@id/azure_communication_ui_call_audio_device_button"
|
||||
android:background="@color/azure_communication_ui_calling_color_button_background_transparent"
|
||||
android:contentDescription="@string/azure_communication_ui_calling_view_more_menu_accessibility_label"
|
||||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_dot_button_22_composite_button_filled"
|
||||
app:layout_constraintEnd_toStartOf="@+id/azure_communication_ui_call_end_call_button"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_audio_device_button"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/azure_communication_ui_call_end_call_button"
|
||||
style="@style/Widget.FluentUI.Button"
|
||||
|
@ -65,7 +81,7 @@
|
|||
android:src="@drawable/azure_communication_ui_calling_ic_fluent_call_end_28_filled_composite_button_filled"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_audio_device_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/azure_communication_ui_call_control_bar_more"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Auf Video umschalten</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Auf Audio umschalten</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Geräteoptionen</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Die Transkription hat begonnen.</b> Indem Sie sich anmelden, erklären Sie
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Auf Video umschalten</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Auf Audio umschalten</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Geräteoptionen</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Die Transkription hat begonnen.</b> Indem Sie sich anmelden, erklären Sie
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Toggle Video</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Toggle Audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Device Options</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Recording has started.</b> By joining, you are
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Toggle Video</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Toggle Audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Device Options</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Recording has started.</b> By joining, you are
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Activar/desactivar vídeo</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Activar/desactivar audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Opciones de dispositivo</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Se ha iniciado la grabación.</b> Al unirse, está
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Activar/desactivar vídeo</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Activar/desactivar audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Opciones de dispositivo</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Se ha iniciado la grabación.</b> Al unirse, está
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Activer/désactiver la vidéo</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Activer/désactiver l’audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Options du périphérique</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>La transcription a démarré.</b> En participant, vous
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Activer/désactiver la vidéo</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Activer/désactiver l’audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Options du périphérique</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>La transcription a démarré.</b> En participant, vous
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Attiva/disattiva video</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Attiva/Disattiva audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Opzioni dispositivo</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>La registrazione è stata avviata.</b> Partecipando,
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Attiva/disattiva video</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Attiva/Disattiva audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Opzioni dispositivo</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>La registrazione è stata avviata.</b> Partecipando,
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">ビデオの切り替え</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">オーディオの切り替え</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">デバイス オプション</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>レコーディングが開始されました。</b> 参加すると、
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">ビデオの切り替え</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">オーディオの切り替え</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">デバイス オプション</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>レコーディングが開始されました。</b> 参加すると、
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">비디오 설정/해제</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">오디오 설정/해제</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">디바이스 옵션</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>녹음을 시작했습니다.</b>참가하면 이 모임을 전사하는데
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">비디오 설정/해제</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">오디오 설정/해제</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">디바이스 옵션</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>녹음을 시작했습니다.</b>참가하면 이 모임을 전사하는데
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Video in-/uitschakelen</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Audio in-/uitschakelen</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Apparaatopties</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Opname is gestart.</b> Door deel te nemen geeft
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Video in-/uitschakelen</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Audio in-/uitschakelen</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Apparaatopties</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Opname is gestart.</b> Door deel te nemen geeft
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Ativar/Desativar Vídeo</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Ativar/Desativar Áudio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Opções do Dispositivo</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>A transcrição foi iniciada.</b> Ingressando, você está
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Ativar/Desativar Vídeo</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Ativar/Desativar Áudio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Opções do Dispositivo</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>A transcrição foi iniciada.</b> Ingressando, você está
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Включить или отключить видео</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Включить или отключить звук</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Параметры устройства</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Началась запись.</b> Присоединяясь, вы
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Включить или отключить видео</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Включить или отключить звук</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Параметры устройства</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Началась запись.</b> Присоединяясь, вы
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Görüntüyü Aç/Kapat</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Sesi Aç/Kapat</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Cihaz Seçenekleri</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Kayıt başlatıldı.</b> Katılarak,
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Görüntüyü Aç/Kapat</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Sesi Aç/Kapat</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Cihaz Seçenekleri</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Kayıt başlatıldı.</b> Katılarak,
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">切换视频</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">切换音频</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">设备选项</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>录制已开始。</b>加入即表示你
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">切換視訊</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">切換音訊</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">裝置選項</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>錄製已開始。</b>一旦加入,即表示您
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">切换视频</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">切换音频</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">设备选项</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>录制已开始。</b>加入即表示你
|
||||
|
|
|
@ -60,6 +60,9 @@
|
|||
<string name="azure_communication_ui_calling_view_button_toggle_video_accessibility_label">Toggle Video</string>
|
||||
<string name="azure_communication_ui_calling_view_button_toggle_audio_accessibility_label">Toggle Audio</string>
|
||||
<string name="azure_communication_ui_calling_view_button_device_options_accessibility_label">Device Options</string>
|
||||
<string name="azure_communication_ui_calling_view_more_menu_accessibility_label">More</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics">Share diagnostics info</string>
|
||||
<string name="azure_communication_ui_calling_view_share_diagnostics_title">Diagnostics info</string>
|
||||
|
||||
<!-- Compliance Banner-->
|
||||
<string name="azure_communication_ui_calling_view_banner_recording_started"><b>Recording has started.</b> By joining, you are
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui
|
||||
|
||||
import com.azure.android.communication.ui.calling.CallCompositeBuilder
|
||||
import com.azure.android.communication.ui.calling.CallCompositeException
|
||||
import com.azure.android.communication.ui.calling.CallCompositeInstanceManager
|
||||
import org.hamcrest.MatcherAssert
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
internal class CallCompositeInstanceManagerTest {
|
||||
@Test
|
||||
fun callCompositeInstanceManager_errorHandling() {
|
||||
val classObj = CallCompositeException::class.java
|
||||
CallCompositeInstanceManager.putCallComposite(0, CallCompositeBuilder().build())
|
||||
|
||||
val ex = Assert.assertThrows(classObj, ::getCallCompositeConfig)
|
||||
MatcherAssert.assertThat(
|
||||
"invalid type: ${ex.javaClass.simpleName}",
|
||||
ex.javaClass.simpleName == classObj.simpleName
|
||||
)
|
||||
MatcherAssert.assertThat(
|
||||
"invalid message, expecting: ${ex.message}",
|
||||
ex.message?.startsWith("This ID is not valid, and no entry exists in the map")
|
||||
?: false
|
||||
)
|
||||
|
||||
MatcherAssert.assertThat(
|
||||
"Invalid cause, expecting: ${ex.cause}",
|
||||
ex.cause is IllegalStateException
|
||||
)
|
||||
}
|
||||
|
||||
private fun getCallCompositeConfig() = CallCompositeInstanceManager.getCallComposite(1)
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.configuration
|
||||
|
||||
import com.azure.android.communication.ui.calling.CallCompositeException
|
||||
import com.azure.android.communication.ui.calling.configuration.CallCompositeConfiguration
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.Assert.assertThrows
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
internal class CallCompositeExceptionTest {
|
||||
|
||||
@Test
|
||||
fun callCompositeConfiguration_errorHandling() {
|
||||
val classObj = CallCompositeException::class.java
|
||||
CallCompositeConfiguration.putConfig(0, CallCompositeConfiguration())
|
||||
|
||||
val ex = assertThrows(classObj, ::getCallCompositeConfig)
|
||||
assertThat(
|
||||
"invalid type: ${ex.javaClass.simpleName}",
|
||||
ex.javaClass.simpleName == classObj.simpleName
|
||||
)
|
||||
assertThat(
|
||||
"invalid message, expecting: ${ex.message}",
|
||||
ex.message?.startsWith("This ID is not valid, and no entry exists in the map") ?: false
|
||||
)
|
||||
|
||||
assertThat(
|
||||
"Invalid cause, expecting: ${ex.cause}",
|
||||
ex.cause is IllegalStateException
|
||||
)
|
||||
}
|
||||
|
||||
private fun getCallCompositeConfig() = CallCompositeConfiguration.getConfig(1)
|
||||
}
|
|
@ -31,6 +31,7 @@ import com.azure.android.communication.ui.calling.redux.state.AudioOperationalSt
|
|||
import com.azure.android.communication.ui.calling.redux.state.AudioDeviceSelectionStatus
|
||||
|
||||
import com.azure.android.communication.ui.ACSBaseTestCoroutine
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.controlbar.more.MoreCallOptionsListViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.hold.OnHoldOverlayViewModel
|
||||
import com.azure.android.communication.ui.calling.presentation.fragment.calling.lobby.LobbyOverlayViewModel
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
|
@ -85,6 +86,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockLobbyOverlayViewModel = mock<LobbyOverlayViewModel>()
|
||||
|
||||
val mockOnHoldOverlayViewModel = mock<OnHoldOverlayViewModel>()
|
||||
val mockMoreCallOptionsListViewModel = mock<MoreCallOptionsListViewModel>()
|
||||
|
||||
val mockCallingViewModelProvider = mock<CallingViewModelFactory> {
|
||||
on { participantGridViewModel } doAnswer { mockParticipantGridViewModel }
|
||||
|
@ -97,6 +99,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
on { bannerViewModel } doAnswer { mockBannerViewModel }
|
||||
on { lobbyOverlayViewModel } doAnswer { mockLobbyOverlayViewModel }
|
||||
on { onHoldOverlayViewModel } doAnswer { mockOnHoldOverlayViewModel }
|
||||
on { moreCallOptionsListViewModel } doAnswer { mockMoreCallOptionsListViewModel }
|
||||
}
|
||||
|
||||
val callingViewModel = CallingViewModel(
|
||||
|
@ -167,6 +170,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockLobbyOverlayViewModel = mock<LobbyOverlayViewModel>()
|
||||
|
||||
val mockOnHoldOverlayViewModel = mock<OnHoldOverlayViewModel>()
|
||||
val mockMoreCallOptionsListViewModel = mock<MoreCallOptionsListViewModel>()
|
||||
|
||||
val mockCallingViewModelProvider = mock<CallingViewModelFactory> {
|
||||
on { participantGridViewModel } doAnswer { mockParticipantGridViewModel }
|
||||
|
@ -179,6 +183,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
on { bannerViewModel } doAnswer { mockBannerViewModel }
|
||||
on { lobbyOverlayViewModel } doAnswer { mockLobbyOverlayViewModel }
|
||||
on { onHoldOverlayViewModel } doAnswer { mockOnHoldOverlayViewModel }
|
||||
on { moreCallOptionsListViewModel } doAnswer { mockMoreCallOptionsListViewModel }
|
||||
}
|
||||
|
||||
val callingViewModel = CallingViewModel(
|
||||
|
@ -248,6 +253,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockBannerViewModel = mock<BannerViewModel>()
|
||||
val mockLobbyOverlayViewModel = mock<LobbyOverlayViewModel>()
|
||||
val mockOnHoldOverlayViewModel = mock<OnHoldOverlayViewModel>()
|
||||
val mockMoreCallOptionsListViewModel = mock<MoreCallOptionsListViewModel>()
|
||||
|
||||
val mockCallingViewModelProvider = mock<CallingViewModelFactory> {
|
||||
on { participantGridViewModel } doAnswer { mockParticipantGridViewModel }
|
||||
|
@ -260,6 +266,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
on { bannerViewModel } doAnswer { mockBannerViewModel }
|
||||
on { lobbyOverlayViewModel } doAnswer { mockLobbyOverlayViewModel }
|
||||
on { onHoldOverlayViewModel } doAnswer { mockOnHoldOverlayViewModel }
|
||||
on { moreCallOptionsListViewModel } doAnswer { mockMoreCallOptionsListViewModel }
|
||||
}
|
||||
|
||||
val callingViewModel = CallingViewModel(
|
||||
|
@ -336,6 +343,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockBannerViewModel = mock<BannerViewModel>()
|
||||
val mockLobbyOverlayViewModel = mock<LobbyOverlayViewModel>()
|
||||
val mockOnHoldOverlayViewModel = mock<OnHoldOverlayViewModel>()
|
||||
val mockMoreCallOptionsListViewModel = mock<MoreCallOptionsListViewModel>()
|
||||
|
||||
val mockCallingViewModelProvider = mock<CallingViewModelFactory> {
|
||||
on { participantGridViewModel } doAnswer { mockParticipantGridViewModel }
|
||||
|
@ -348,6 +356,7 @@ internal class CallingViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
on { bannerViewModel } doAnswer { mockBannerViewModel }
|
||||
on { lobbyOverlayViewModel } doAnswer { mockLobbyOverlayViewModel }
|
||||
on { onHoldOverlayViewModel } doAnswer { mockOnHoldOverlayViewModel }
|
||||
on { moreCallOptionsListViewModel } doAnswer { mockMoreCallOptionsListViewModel }
|
||||
}
|
||||
|
||||
val callingViewModel = CallingViewModel(
|
||||
|
|
|
@ -124,7 +124,10 @@ internal class ControlBarViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
AudioOperationalStatus.OFF,
|
||||
audioDeviceState,
|
||||
BluetoothState(available = false, deviceName = "bluetooth")
|
||||
)
|
||||
),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
)
|
||||
|
||||
val expectedAudioOperationalStatus1 = AudioOperationalStatus.ON
|
||||
|
@ -208,7 +211,10 @@ internal class ControlBarViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
AudioOperationalStatus.OFF,
|
||||
audioDeviceState,
|
||||
BluetoothState(available = false, deviceName = "bluetooth")
|
||||
)
|
||||
),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
)
|
||||
|
||||
val flowJob = launch {
|
||||
|
@ -296,7 +302,10 @@ internal class ControlBarViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
AudioOperationalStatus.OFF,
|
||||
audioDeviceState,
|
||||
BluetoothState(available = false, deviceName = "bluetooth")
|
||||
)
|
||||
),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
)
|
||||
|
||||
val resultListFromCameraStateFlow = mutableListOf<ControlBarViewModel.CameraModel>()
|
||||
|
@ -377,7 +386,10 @@ internal class ControlBarViewModelUnitTest : ACSBaseTestCoroutine() {
|
|||
AudioOperationalStatus.OFF,
|
||||
audioDeviceState,
|
||||
BluetoothState(available = false, deviceName = "bluetooth")
|
||||
)
|
||||
),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
)
|
||||
|
||||
val resultListFromOnHoldCallStatusStateFlow = mutableListOf<Boolean>()
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.presentation.manager
|
||||
|
||||
import com.azure.android.communication.ui.ACSBaseTestCoroutine
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.DiagnosticsManagerImpl
|
||||
import com.azure.android.communication.ui.calling.redux.AppStore
|
||||
import com.azure.android.communication.ui.calling.redux.state.AppReduxState
|
||||
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.ReduxState
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import org.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.mock
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
internal class DiagnosticsManagerTest : ACSBaseTestCoroutine() {
|
||||
|
||||
@Test
|
||||
@ExperimentalCoroutinesApi
|
||||
fun diagnosticsManager_getCallId_returns_callId() {
|
||||
|
||||
runScopedTest {
|
||||
// arrange
|
||||
val appState1 = AppReduxState("")
|
||||
|
||||
val stateFlow = MutableStateFlow<ReduxState>(appState1)
|
||||
val mockAppStore = mock<AppStore<ReduxState>> {
|
||||
on { getStateFlow() } doAnswer { stateFlow }
|
||||
}
|
||||
|
||||
val diagnosticsManager: DiagnosticsManager = DiagnosticsManagerImpl(mockAppStore)
|
||||
val flowJob = launch {
|
||||
diagnosticsManager.start(coroutineScope = this)
|
||||
}
|
||||
|
||||
val diagnosticsInfo1 = diagnosticsManager.diagnosticsInfo
|
||||
Assert.assertNotNull(diagnosticsInfo1)
|
||||
Assert.assertNull(diagnosticsInfo1.lastKnownCallId)
|
||||
|
||||
// update state
|
||||
val appState2 = AppReduxState("")
|
||||
val callID = "callID"
|
||||
appState2.callState = CallingState(CallingStatus.CONNECTING, callID)
|
||||
stateFlow.value = appState2
|
||||
|
||||
val diagnosticsInfo2 = diagnosticsManager.diagnosticsInfo
|
||||
Assert.assertNotSame(diagnosticsInfo1, diagnosticsInfo2)
|
||||
Assert.assertNotNull(diagnosticsInfo2)
|
||||
Assert.assertEquals(callID, diagnosticsInfo2.lastKnownCallId)
|
||||
|
||||
// redux state loosing CallID
|
||||
|
||||
// update state
|
||||
val appState3 = AppReduxState("")
|
||||
appState3.callState = CallingState(CallingStatus.CONNECTING, null)
|
||||
stateFlow.value = appState3
|
||||
|
||||
val diagnosticsInfo3 = diagnosticsManager.diagnosticsInfo
|
||||
Assert.assertSame(diagnosticsInfo2, diagnosticsInfo3)
|
||||
Assert.assertNotNull(diagnosticsInfo3)
|
||||
Assert.assertEquals(callID, diagnosticsInfo3.lastKnownCallId)
|
||||
flowJob.cancel()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -365,6 +365,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -386,6 +387,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockCallingService: CallingService = mock {
|
||||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -442,6 +444,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
MutableSharedFlow()
|
||||
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -450,6 +453,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockCallingService: CallingService = mock {
|
||||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -542,6 +546,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -551,6 +556,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn startCallCompletableFuture
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
|
@ -611,6 +617,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -620,6 +627,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn startCallCompletableFuture
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
|
@ -673,6 +681,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -682,6 +691,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn startCallCompletableFuture
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -735,6 +745,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -744,6 +755,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn startCallCompletableFuture
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
|
@ -797,6 +809,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -805,6 +818,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn startCallCompletableFuture
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1428,6 +1442,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1437,6 +1452,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1499,6 +1515,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow =
|
||||
MutableStateFlow(CallInfoModel(CallingStatus.LOCAL_HOLD, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1508,7 +1525,9 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockCallingService: CallingService = mock {
|
||||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1551,6 +1570,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1560,6 +1580,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1618,6 +1639,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val camerasCountUpdatedStateFlow = MutableStateFlow(2)
|
||||
|
@ -1626,6 +1648,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1679,6 +1702,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1688,6 +1712,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1745,6 +1770,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1754,6 +1780,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1809,6 +1836,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1818,6 +1846,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1889,6 +1918,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1898,6 +1928,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -1957,6 +1988,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val callingServiceParticipantsSharedFlow =
|
||||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow = MutableStateFlow(CallInfoModel(CallingStatus.NONE, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -1966,6 +1998,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
@ -2049,6 +2082,7 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
MutableSharedFlow<MutableMap<String, ParticipantInfoModel>>()
|
||||
val callInfoModelStateFlow =
|
||||
MutableStateFlow(CallInfoModel(CallingStatus.LOCAL_HOLD, null))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -2058,7 +2092,9 @@ internal class CallingMiddlewareActionHandlerUnitTest : ACSBaseTestCoroutine() {
|
|||
val mockCallingService: CallingService = mock {
|
||||
on { getParticipantsInfoModelSharedFlow() } doReturn callingServiceParticipantsSharedFlow
|
||||
on { startCall(any(), any()) } doReturn CompletableFuture<Void>()
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getCallInfoModelEventSharedFlow() } doReturn callInfoModelStateFlow
|
||||
on { getCallIdStateFlow() } doReturn callIdFlow
|
||||
on { getIsMutedSharedFlow() } doReturn isMutedSharedFlow
|
||||
on { getIsRecordingSharedFlow() } doReturn isRecordingSharedFlow
|
||||
on { getIsTranscribingSharedFlow() } doReturn isTranscribingSharedFlow
|
||||
|
|
|
@ -60,6 +60,7 @@ internal class CallingServiceUnitTests : ACSBaseTestCoroutine() {
|
|||
|
||||
val callingStateWrapperStateFlow =
|
||||
MutableStateFlow(CallingStateWrapper(callState, 0))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -68,6 +69,8 @@ internal class CallingServiceUnitTests : ACSBaseTestCoroutine() {
|
|||
.thenReturn(remoteParticipantsInfoModelSharedFlow)
|
||||
Mockito.`when`(mockCallingGateway.getCallingStateWrapperSharedFlow())
|
||||
.thenReturn(callingStateWrapperStateFlow)
|
||||
Mockito.`when`(mockCallingGateway.getCallIdStateFlow())
|
||||
.thenReturn(callIdFlow)
|
||||
Mockito.`when`(mockCallingGateway.getIsMutedSharedFlow())
|
||||
.thenReturn(isMutedSharedFlow)
|
||||
Mockito.`when`(mockCallingGateway.getIsRecordingSharedFlow())
|
||||
|
@ -273,6 +276,7 @@ internal class CallingServiceUnitTests : ACSBaseTestCoroutine() {
|
|||
|
||||
val callingStateWrapperStateFlow =
|
||||
MutableStateFlow(CallingStateWrapper(CallState.NONE, 0))
|
||||
val callIdFlow = MutableStateFlow<String?>(null)
|
||||
val isMutedSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isRecordingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
val isTranscribingSharedFlow = MutableSharedFlow<Boolean>()
|
||||
|
@ -281,7 +285,8 @@ internal class CallingServiceUnitTests : ACSBaseTestCoroutine() {
|
|||
.thenReturn(remoteParticipantsInfoModelSharedFlow)
|
||||
Mockito.`when`(mockCallingGateway.getRemoteParticipantInfoModelSharedFlow())
|
||||
.thenReturn(remoteParticipantsInfoModelSharedFlow)
|
||||
|
||||
Mockito.`when`(mockCallingGateway.getCallIdStateFlow())
|
||||
.thenReturn(callIdFlow)
|
||||
Mockito.`when`(mockCallingGateway.getCallingStateWrapperSharedFlow())
|
||||
.thenReturn(callingStateWrapperStateFlow)
|
||||
Mockito.`when`(mockCallingGateway.getIsMutedSharedFlow())
|
||||
|
|
|
@ -18,16 +18,16 @@ class CallingCompositeAudioDeviceListTest : BaseUiTest() {
|
|||
@Test
|
||||
fun selectDefaultAudioDevice() {
|
||||
joinGroupSetupScreen()
|
||||
.selectAndroidAudioDevice(false)
|
||||
.verifyIsAndroidAudioDevice()
|
||||
.selectSpeakerAudioDevice(true)
|
||||
.verifyIsSpeakerAudioDevice()
|
||||
.navigateUpFromSetupScreen()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun selectSpeakerAudioDevice() {
|
||||
fun selectAndroidAudioDevice() {
|
||||
joinGroupSetupScreen()
|
||||
.selectSpeakerAudioDevice(true)
|
||||
.verifyIsSpeakerAudioDevice()
|
||||
.selectAndroidAudioDevice(false)
|
||||
.verifyIsAndroidAudioDevice()
|
||||
.navigateUpFromSetupScreen()
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
package com.azure.android.communication.ui.callingcompositedemoapp
|
||||
|
||||
import com.azure.android.communication.ui.calling.CallComposite
|
||||
import com.azure.android.communication.ui.calling.CallCompositeEventHandler
|
||||
import com.azure.android.communication.ui.calling.models.CallCompositeErrorEvent
|
||||
import java.lang.ref.WeakReference
|
||||
|
@ -10,7 +11,10 @@ import java.lang.ref.WeakReference
|
|||
// Handles forwarding of error messages to the CallLauncherActivity
|
||||
//
|
||||
// CallLauncherActivity is loosely coupled and will detach the weak reference after disposed.
|
||||
class CallLauncherActivityErrorHandler(callLauncherActivity: CallLauncherActivity) :
|
||||
class CallLauncherActivityErrorHandler(
|
||||
private val callComposite: CallComposite,
|
||||
callLauncherActivity: CallLauncherActivity
|
||||
) :
|
||||
CallCompositeEventHandler<CallCompositeErrorEvent> {
|
||||
|
||||
private val activityWr: WeakReference<CallLauncherActivity> =
|
||||
|
@ -18,9 +22,10 @@ class CallLauncherActivityErrorHandler(callLauncherActivity: CallLauncherActivit
|
|||
|
||||
override fun handle(it: CallCompositeErrorEvent) {
|
||||
println("================= application is logging exception =================")
|
||||
println("call id: " + (callComposite.diagnosticsInfo.lastKnownCallId ?: ""))
|
||||
println(it.cause)
|
||||
println(it.errorCode)
|
||||
activityWr.get()?.showAlert(it.errorCode.toString() + " " + it.cause?.message)
|
||||
activityWr.get()?.showAlert("${it.errorCode} ${it.cause?.message}. Call id: ${callComposite.diagnosticsInfo.lastKnownCallId ?: ""}")
|
||||
println("====================================================================")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import kotlin.Unit;
|
|||
import kotlin.jvm.functions.Function1;
|
||||
|
||||
public class CallingCompositeJavaLauncher implements CallingCompositeLauncher {
|
||||
private static CallComposite callComposite;
|
||||
private final Callable<String> tokenRefresher;
|
||||
|
||||
public CallingCompositeJavaLauncher(final Callable<String> tokenRefresher) {
|
||||
|
@ -57,7 +58,7 @@ public class CallingCompositeJavaLauncher implements CallingCompositeLauncher {
|
|||
}
|
||||
|
||||
final CallComposite callComposite = builder.build();
|
||||
callComposite.addOnErrorEventHandler(new CallLauncherActivityErrorHandler(callLauncherActivity));
|
||||
callComposite.addOnErrorEventHandler(new CallLauncherActivityErrorHandler(callComposite, callLauncherActivity));
|
||||
|
||||
if (SettingsFeatures.getRemoteParticipantPersonaInjectionSelection()) {
|
||||
callComposite.addOnRemoteParticipantJoinedEventHandler(
|
||||
|
@ -84,5 +85,8 @@ public class CallingCompositeJavaLauncher implements CallingCompositeLauncher {
|
|||
.setTitleAndSubtitle(SettingsFeatures.getTitle(), SettingsFeatures.getSubtitle()));
|
||||
|
||||
callComposite.launch(callLauncherActivity, remoteOptions, localOptions);
|
||||
|
||||
// For test purposes we will keep a static ref to CallComposite
|
||||
this.callComposite = callComposite;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class CallingCompositeKotlinLauncher(private val tokenRefresher: Callable<String
|
|||
val selectedLanguage = language()
|
||||
val locale = selectedLanguage?.let { locale(it) }
|
||||
|
||||
val callComposite: CallComposite =
|
||||
val callComposite =
|
||||
if (AdditionalFeatures.secondaryThemeFeature.active)
|
||||
CallCompositeBuilder().theme(R.style.MyCompany_Theme_Calling)
|
||||
.localization(CallCompositeLocalizationOptions(locale!!, getLayoutDirection()))
|
||||
|
@ -54,7 +54,7 @@ class CallingCompositeKotlinLauncher(private val tokenRefresher: Callable<String
|
|||
.localization(CallCompositeLocalizationOptions(locale!!, getLayoutDirection()))
|
||||
.build()
|
||||
|
||||
callComposite.addOnErrorEventHandler(CallLauncherActivityErrorHandler(callLauncherActivity))
|
||||
callComposite.addOnErrorEventHandler(CallLauncherActivityErrorHandler(callComposite, callLauncherActivity))
|
||||
|
||||
if (getRemoteParticipantPersonaInjectionSelection()) {
|
||||
callComposite.addOnRemoteParticipantJoinedEventHandler(
|
||||
|
@ -82,5 +82,12 @@ class CallingCompositeKotlinLauncher(private val tokenRefresher: Callable<String
|
|||
)
|
||||
|
||||
callComposite.launch(callLauncherActivity, remoteOptions, localOptions)
|
||||
|
||||
// For test purposes we will keep a static ref to CallComposite
|
||||
CallingCompositeKotlinLauncher.callComposite = callComposite
|
||||
}
|
||||
|
||||
companion object {
|
||||
var callComposite: CallComposite? = null
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче