diff --git a/widgetssdk/src/main/java/com/glia/widgets/core/secureconversations/domain/HasOngoingSecureConversationUseCase.kt b/widgetssdk/src/main/java/com/glia/widgets/core/secureconversations/domain/HasOngoingSecureConversationUseCase.kt index 0e6b50031..308a94cc8 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/core/secureconversations/domain/HasOngoingSecureConversationUseCase.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/core/secureconversations/domain/HasOngoingSecureConversationUseCase.kt @@ -1,5 +1,6 @@ package com.glia.widgets.core.secureconversations.domain +import com.glia.widgets.chat.domain.IsAuthenticatedUseCase import com.glia.widgets.core.secureconversations.SecureConversationsRepository import com.glia.widgets.engagement.State import com.glia.widgets.engagement.domain.EngagementStateUseCase @@ -9,6 +10,7 @@ import io.reactivex.rxjava3.core.Flowable internal class HasOngoingSecureConversationUseCase( private val secureConversationsRepository: SecureConversationsRepository, + private val isAuthenticatedUseCase: IsAuthenticatedUseCase, private val engagementStateUseCase: EngagementStateUseCase ) { /** @@ -20,7 +22,8 @@ internal class HasOngoingSecureConversationUseCase( secureConversationsRepository.unreadMessagesCountObservable, engagementStateUseCase() ) { pendingSecureConversations, unreadMessagesCount, state -> - pendingSecureConversations || unreadMessagesCount > 0 || state is State.TransferredToSecureConversation + isAuthenticatedUseCase() && + (pendingSecureConversations || unreadMessagesCount > 0 || state is State.TransferredToSecureConversation) } operator fun invoke(): Flowable = hasOngoingInteraction.distinctUntilChanged().observeOn(AndroidSchedulers.mainThread()) diff --git a/widgetssdk/src/main/java/com/glia/widgets/di/ControllerFactory.java b/widgetssdk/src/main/java/com/glia/widgets/di/ControllerFactory.java index 9987244d9..8b3be38ac 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/di/ControllerFactory.java +++ b/widgetssdk/src/main/java/com/glia/widgets/di/ControllerFactory.java @@ -390,8 +390,11 @@ public EntryWidgetContract.Controller getEntryWidgetController() { useCaseFactory.createIsAuthenticatedUseCase(), repositoryFactory.getSecureConversationsRepository(), useCaseFactory.getHasPendingSecureConversationsWithTimeoutUseCase(), + useCaseFactory.getEngagementStateUseCase(), + useCaseFactory.getEngagementTypeUseCase(), core, - Dependencies.getEngagementLauncher() + Dependencies.getEngagementLauncher(), + Dependencies.getActivityLauncher() ); } diff --git a/widgetssdk/src/main/java/com/glia/widgets/di/Dependencies.kt b/widgetssdk/src/main/java/com/glia/widgets/di/Dependencies.kt index 9f66a6908..b091416ff 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/di/Dependencies.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/di/Dependencies.kt @@ -76,6 +76,7 @@ internal object Dependencies { @JvmStatic val configurationManager: ConfigurationManager by lazy { ConfigurationManagerImpl() } + @JvmStatic val activityLauncher: ActivityLauncher by lazy { ActivityLauncherImpl(IntentHelperImpl(), repositoryFactory.engagementRepository) } diff --git a/widgetssdk/src/main/java/com/glia/widgets/di/UseCaseFactory.java b/widgetssdk/src/main/java/com/glia/widgets/di/UseCaseFactory.java index f2656ea00..58538ed05 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/di/UseCaseFactory.java +++ b/widgetssdk/src/main/java/com/glia/widgets/di/UseCaseFactory.java @@ -875,6 +875,7 @@ public EngagementTypeUseCase getEngagementTypeUseCase() { return new EngagementTypeUseCaseImpl( getIsQueueingOrEngagementUseCase(), getIsCurrentEngagementCallVisualizer(), + getScreenSharingUseCase(), getOperatorMediaUseCase(), getVisitorMediaUseCase(), getIsOperatorPresentUseCase() @@ -1057,6 +1058,7 @@ public FlipCameraButtonStateUseCase getFlipCameraButtonStateUseCase() { public HasOngoingSecureConversationUseCase getHasPendingSecureConversationsWithTimeoutUseCase() { return new HasOngoingSecureConversationUseCase( repositoryFactory.getSecureConversationsRepository(), + createIsAuthenticatedUseCase(), getEngagementStateUseCase() ); } diff --git a/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/EngagementTypeUseCase.kt b/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/EngagementTypeUseCase.kt index 161267415..4fee50521 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/EngagementTypeUseCase.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/EngagementTypeUseCase.kt @@ -1,21 +1,48 @@ package com.glia.widgets.engagement.domain +import com.glia.androidsdk.Engagement.MediaType +import com.glia.widgets.helper.hasAudio +import com.glia.widgets.helper.hasVideo +import io.reactivex.rxjava3.core.Flowable + internal interface EngagementTypeUseCase { + val isAudioEngagement: Boolean + val isVideoEngagement: Boolean val isMediaEngagement: Boolean val isChatEngagement: Boolean + val isCallVisualizer: Boolean val isCallVisualizerScreenSharing: Boolean + + operator fun invoke(): Flowable } internal class EngagementTypeUseCaseImpl( private val isQueueingOrLiveEngagementUseCase: IsQueueingOrLiveEngagementUseCase, private val isCurrentEngagementCallVisualizerUseCase: IsCurrentEngagementCallVisualizerUseCase, + private val screenSharingUseCase: ScreenSharingUseCase, private val operatorMediaUseCase: OperatorMediaUseCase, private val visitorMediaUseCase: VisitorMediaUseCase, - private val isOperatorPresentUseCase: IsOperatorPresentUseCase + private val isOperatorPresentUseCase: IsOperatorPresentUseCase, ) : EngagementTypeUseCase { private val hasOngoingEngagement get() = isQueueingOrLiveEngagementUseCase.hasOngoingLiveEngagement + private val hasAudio: Boolean get() = visitorMediaUseCase.hasAudio || operatorMediaUseCase.hasAudio + private val hasVideo: Boolean get() = visitorMediaUseCase.hasVideo || operatorMediaUseCase.hasVideo + override val isAudioEngagement: Boolean get() = hasOngoingEngagement && isOperatorPresentUseCase() && hasAudio + override val isVideoEngagement: Boolean get() = hasOngoingEngagement && isOperatorPresentUseCase() && hasVideo private val hasAnyMedia: Boolean get() = visitorMediaUseCase.hasMedia || operatorMediaUseCase.hasMedia override val isMediaEngagement: Boolean get() = hasOngoingEngagement && isOperatorPresentUseCase() && hasAnyMedia override val isChatEngagement: Boolean get() = hasOngoingEngagement && !isCurrentEngagementCallVisualizerUseCase() && isOperatorPresentUseCase() && !hasAnyMedia - override val isCallVisualizerScreenSharing: Boolean get() = isCurrentEngagementCallVisualizerUseCase() && !hasAnyMedia + override val isCallVisualizer: Boolean get() = isCurrentEngagementCallVisualizerUseCase() + override val isCallVisualizerScreenSharing: Boolean get() = isCurrentEngagementCallVisualizerUseCase() && screenSharingUseCase.isSharing + private val operatorMediaObservable by lazy { operatorMediaUseCase() } + + override fun invoke(): Flowable { + return operatorMediaObservable.map { operatorMediaState -> + when { + operatorMediaState.hasVideo -> MediaType.VIDEO + operatorMediaState.hasAudio -> MediaType.AUDIO + else -> MediaType.UNKNOWN + } + } + } } diff --git a/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/OperatorMediaUseCase.kt b/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/OperatorMediaUseCase.kt index d6a07ea3a..7942b3c6f 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/OperatorMediaUseCase.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/OperatorMediaUseCase.kt @@ -3,10 +3,14 @@ package com.glia.widgets.engagement.domain import com.glia.androidsdk.comms.MediaState import com.glia.widgets.engagement.EngagementRepository import com.glia.widgets.helper.Data +import com.glia.widgets.helper.hasAudio import com.glia.widgets.helper.hasMedia +import com.glia.widgets.helper.hasVideo import io.reactivex.rxjava3.core.Flowable internal interface OperatorMediaUseCase { + val hasAudio: Boolean + val hasVideo: Boolean val hasMedia: Boolean operator fun invoke(): Flowable } @@ -16,6 +20,8 @@ internal class OperatorMediaUseCaseImpl(private val engagementRepository: Engage .filter(Data::hasValue) .map { it as Data.Value } .map(Data.Value::result) + override val hasAudio: Boolean get() = engagementRepository.operatorCurrentMediaState?.hasAudio ?: false + override val hasVideo: Boolean get() = engagementRepository.operatorCurrentMediaState?.hasVideo ?: false override val hasMedia: Boolean get() = engagementRepository.operatorCurrentMediaState?.hasMedia ?: false override fun invoke(): Flowable = operatorMediaState diff --git a/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/VisitorMediaUseCase.kt b/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/VisitorMediaUseCase.kt index e442da9d5..d8078ee77 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/VisitorMediaUseCase.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/engagement/domain/VisitorMediaUseCase.kt @@ -3,10 +3,14 @@ package com.glia.widgets.engagement.domain import com.glia.androidsdk.comms.MediaState import com.glia.widgets.engagement.EngagementRepository import com.glia.widgets.helper.Data +import com.glia.widgets.helper.hasAudio import com.glia.widgets.helper.hasMedia +import com.glia.widgets.helper.hasVideo import io.reactivex.rxjava3.core.Flowable internal interface VisitorMediaUseCase { + val hasAudio: Boolean + val hasVideo: Boolean val hasMedia: Boolean val onHoldState: Flowable operator fun invoke(): Flowable @@ -19,6 +23,8 @@ internal class VisitorMediaUseCaseImpl(private val engagementRepository: Engagem .map(Data.Value::result) override val onHoldState: Flowable = engagementRepository.onHoldState + override val hasAudio: Boolean get() = engagementRepository.visitorCurrentMediaState?.hasAudio ?: false + override val hasVideo: Boolean get() = engagementRepository.visitorCurrentMediaState?.hasVideo ?: false override val hasMedia: Boolean get() = engagementRepository.visitorCurrentMediaState?.hasMedia ?: false diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetContract.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetContract.kt index bda469242..51d3df786 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetContract.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetContract.kt @@ -17,9 +17,14 @@ internal interface EntryWidgetContract { sealed class ItemType(private val order: Int = HIGHEST_ORDER) : Comparable { data object VideoCall : ItemType(order = 0) - data object AudioCall : ItemType(order = 1) - data object Chat : ItemType(order = 2) - data class Messaging(val value: Int) : ItemType(order = 3) + data object VideoCallOngoing : ItemType(order = 1) + data object AudioCall : ItemType(order = 2) + data object AudioCallOngoing : ItemType(order = 3) + data object Chat : ItemType(order = 4) + data object ChatOngoing : ItemType(order = 5) + data class Messaging(val value: Int) : ItemType(order = 6) + data class MessagingOngoing(val value: Int) : ItemType(order = 7) + data object CallVisualizerOngoing : ItemType(order = 8) data object LoadingState : ItemType() data object EmptyState : ItemType() data object SdkNotInitializedState : ItemType() diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetController.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetController.kt index c195e1d0f..31431d267 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetController.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/EntryWidgetController.kt @@ -1,17 +1,22 @@ package com.glia.widgets.entrywidget import android.app.Activity -import com.glia.androidsdk.Engagement +import com.glia.androidsdk.Engagement.MediaType import com.glia.androidsdk.queuing.Queue +import com.glia.widgets.chat.Intention import com.glia.widgets.chat.domain.IsAuthenticatedUseCase import com.glia.widgets.core.queue.QueueRepository import com.glia.widgets.core.queue.QueuesState import com.glia.widgets.core.secureconversations.SecureConversationsRepository import com.glia.widgets.core.secureconversations.domain.HasOngoingSecureConversationUseCase import com.glia.widgets.di.GliaCore +import com.glia.widgets.engagement.State +import com.glia.widgets.engagement.domain.EngagementStateUseCase +import com.glia.widgets.engagement.domain.EngagementTypeUseCase import com.glia.widgets.helper.Logger import com.glia.widgets.helper.TAG import com.glia.widgets.helper.mediaTypes +import com.glia.widgets.launcher.ActivityLauncher import com.glia.widgets.launcher.EngagementLauncher import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Flowable @@ -22,13 +27,18 @@ internal class EntryWidgetController @JvmOverloads constructor( private val isAuthenticatedUseCase: IsAuthenticatedUseCase, private val secureConversationsRepository: SecureConversationsRepository, private val hasOngoingSecureConversationUseCase: HasOngoingSecureConversationUseCase, + private val engagementStateUseCase: EngagementStateUseCase, + private val engagementTypeUseCase: EngagementTypeUseCase, private val core: GliaCore, private val engagementLauncher: EngagementLauncher, + private val activityLauncher: ActivityLauncher, private val compositeDisposable: CompositeDisposable = CompositeDisposable() ) : EntryWidgetContract.Controller { private val queueStateObservable by lazy { queueRepository.queuesState } private val unreadMessagesCountObservable by lazy { secureConversationsRepository.unreadMessagesCountObservable } private val hasOngoingSCObservable by lazy { hasOngoingSecureConversationUseCase() } + private val engagementStateObservable by lazy { engagementStateUseCase() } + private val mediaTypeObservable by lazy { engagementTypeUseCase() } private val loadingState: List by lazy { listOf( @@ -51,7 +61,14 @@ internal class EntryWidgetController @JvmOverloads constructor( get() = queueStateObservable.map(::mapMessagingQueueState) private val entryWidgetObservableItemType: Flowable> - get() = Flowable.combineLatest(queueStateObservable, unreadMessagesCountObservable, hasOngoingSCObservable, ::mapEntryWidgetQueueState) + get() = Flowable.combineLatest( + engagementStateObservable, + mediaTypeObservable.startWithItem(MediaType.UNKNOWN), + queueStateObservable, + unreadMessagesCountObservable, + hasOngoingSCObservable, + ::mapToEntryWidgetItems + ) private lateinit var view: EntryWidgetContract.View @@ -68,6 +85,38 @@ internal class EntryWidgetController @JvmOverloads constructor( .let(compositeDisposable::add) } + private fun mapToEntryWidgetItems( + engagementState: State, + mediaType: MediaType, + queuesState: QueuesState, + unreadMessagesCount: Int, + hasOngoingSC: Boolean, + ): List { + val items = when (engagementState) { + is State.Update -> prepareItemsBasedOnOngoingEngagement(mediaType, unreadMessagesCount, hasOngoingSC).toMutableList() + is State.FinishedOmniCore, State.FinishedCallVisualizer -> prepareItemsBasedOnQueues(queuesState, unreadMessagesCount, hasOngoingSC).toMutableList() + else -> prepareItemsBasedOnQueues(queuesState, unreadMessagesCount, hasOngoingSC).toMutableList() + } + if (!view.whiteLabel) { + items.add(EntryWidgetContract.ItemType.PoweredBy) + } + return items.apply { sort() } + } + + private fun prepareItemsBasedOnOngoingEngagement( + mediaType: MediaType, + unreadMessagesCount: Int, + hasOngoingSC: Boolean + ): List { + return when { + engagementTypeUseCase.isCallVisualizer -> listOf(EntryWidgetContract.ItemType.CallVisualizerOngoing) + hasOngoingSC -> listOf(EntryWidgetContract.ItemType.MessagingOngoing(unreadMessagesCount)) + mediaType == MediaType.VIDEO -> listOf(EntryWidgetContract.ItemType.VideoCallOngoing) + mediaType == MediaType.AUDIO -> listOf(EntryWidgetContract.ItemType.AudioCallOngoing) + else -> listOf(EntryWidgetContract.ItemType.ChatOngoing) + } + } + private fun itemsObservableBasedOnType(type: EntryWidgetContract.ViewType) = when (type) { EntryWidgetContract.ViewType.MESSAGING_LIVE_SUPPORT -> messagingChatObservableItemType else -> entryWidgetObservableItemType @@ -82,7 +131,7 @@ internal class EntryWidgetController @JvmOverloads constructor( view.showItems(items) } - private fun mapEntryWidgetQueueState( + private fun prepareItemsBasedOnQueues( queuesState: QueuesState, unreadMessagesCount: Int, hasOngoingSC: Boolean @@ -94,23 +143,17 @@ internal class EntryWidgetController @JvmOverloads constructor( * Sometimes(when we authenticate with opened Entry Widget embedded view), * we receive updates for ongoing secure conversations before the authentication result is saved, causing this check to return false. */ if (hasOngoingSC && isAuthenticatedUseCase()) - listOf(EntryWidgetContract.ItemType.Messaging(unreadMessagesCount)) + listOf(EntryWidgetContract.ItemType.MessagingOngoing(unreadMessagesCount)) else default } - val items = when (queuesState) { + return when (queuesState) { QueuesState.Empty -> messagingOrDefault(emptyState) QueuesState.Loading -> messagingOrDefault(loadingState) is QueuesState.Error -> messagingOrDefault(errorState) is QueuesState.Queues -> mapEntryWidgetQueues(queuesState.queues, unreadMessagesCount, hasOngoingSC) - }.toMutableList() - - if (!view.whiteLabel) { - items.add(EntryWidgetContract.ItemType.PoweredBy) } - - return items.apply { sort() } } private fun mapEntryWidgetQueues(queues: List, unreadMessagesCount: Int, hasOngoingSC: Boolean): List { @@ -118,10 +161,10 @@ internal class EntryWidgetController @JvmOverloads constructor( val items = queues.mediaTypes.mapNotNull { when { - it == Engagement.MediaType.VIDEO -> EntryWidgetContract.ItemType.VideoCall - it == Engagement.MediaType.AUDIO -> EntryWidgetContract.ItemType.AudioCall - it == Engagement.MediaType.TEXT -> EntryWidgetContract.ItemType.Chat - it == Engagement.MediaType.MESSAGING && isAuthenticatedUseCase() -> messaging + it == MediaType.VIDEO -> EntryWidgetContract.ItemType.VideoCall + it == MediaType.AUDIO -> EntryWidgetContract.ItemType.AudioCall + it == MediaType.TEXT -> EntryWidgetContract.ItemType.Chat + it == MediaType.MESSAGING && isAuthenticatedUseCase() -> messaging else -> null } @@ -141,9 +184,9 @@ internal class EntryWidgetController @JvmOverloads constructor( is QueuesState.Error -> errorState is QueuesState.Queues -> queuesState.queues.mediaTypes.mapNotNull { mediaType -> when (mediaType) { - Engagement.MediaType.VIDEO -> EntryWidgetContract.ItemType.VideoCall - Engagement.MediaType.AUDIO -> EntryWidgetContract.ItemType.AudioCall - Engagement.MediaType.TEXT -> EntryWidgetContract.ItemType.Chat + MediaType.VIDEO -> EntryWidgetContract.ItemType.VideoCall + MediaType.AUDIO -> EntryWidgetContract.ItemType.AudioCall + MediaType.TEXT -> EntryWidgetContract.ItemType.Chat else -> null } }.takeIf { it.isNotEmpty() }?.sorted() ?: emptyState @@ -153,10 +196,20 @@ internal class EntryWidgetController @JvmOverloads constructor( Logger.d(TAG, "Item clicked: $itemType") when (itemType) { - EntryWidgetContract.ItemType.Chat -> engagementLauncher.startChat(activity) - EntryWidgetContract.ItemType.AudioCall -> engagementLauncher.startAudioCall(activity) EntryWidgetContract.ItemType.VideoCall -> engagementLauncher.startVideoCall(activity) - is EntryWidgetContract.ItemType.Messaging -> engagementLauncher.startSecureMessaging(activity) + EntryWidgetContract.ItemType.VideoCallOngoing -> activityLauncher.launchCall(activity, null, false) + EntryWidgetContract.ItemType.AudioCall -> engagementLauncher.startAudioCall(activity) + EntryWidgetContract.ItemType.AudioCallOngoing -> activityLauncher.launchCall(activity, null, false) + EntryWidgetContract.ItemType.Chat -> engagementLauncher.startChat(activity) + EntryWidgetContract.ItemType.ChatOngoing -> activityLauncher.launchChat(activity, Intention.RETURN_TO_CHAT) + is EntryWidgetContract.ItemType.Messaging, + is EntryWidgetContract.ItemType.MessagingOngoing -> engagementLauncher.startSecureMessaging(activity) + + is EntryWidgetContract.ItemType.CallVisualizerOngoing -> { + if (engagementTypeUseCase.isMediaEngagement) activityLauncher.launchCall(activity, null, false) + else if (engagementTypeUseCase.isCallVisualizerScreenSharing) activityLauncher.launchEndScreenSharing(activity) + } + EntryWidgetContract.ItemType.ErrorState -> onRetryButtonClicked() else -> {} } diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetAdapter.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetAdapter.kt index 583561a0f..6cdea6661 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetAdapter.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetAdapter.kt @@ -5,6 +5,7 @@ import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import com.glia.widgets.databinding.EntryWidgetCallVisualizerItemBinding import com.glia.widgets.databinding.EntryWidgetErrorItemBinding import com.glia.widgets.databinding.EntryWidgetLiveItemBinding import com.glia.widgets.databinding.EntryWidgetMessagingItemBinding @@ -84,6 +85,7 @@ internal class EntryWidgetAdapter( enum class ViewType { LIVE_MEDIA_TYPE_ITEMS, MESSAGING_MEDIA_TYPE_ITEM, + CALL_VISUALIZER_ITEM, ERROR_ITEM, PROVIDED_BY_ITEM } @@ -105,6 +107,10 @@ internal class EntryWidgetAdapter( EntryWidgetMessagingItemBinding.inflate(parent.layoutInflater, parent, false), itemTheme = mediaTypeItemsTheme?.mediaTypeItem ) + ViewType.CALL_VISUALIZER_ITEM.ordinal -> EntryWidgetCallVisualizerItemViewHolder( + EntryWidgetCallVisualizerItemBinding.inflate(parent.layoutInflater, parent, false), + itemTheme = mediaTypeItemsTheme?.mediaTypeItem + ) else -> EntryWidgetLiveItemViewHolder( EntryWidgetLiveItemBinding.inflate(parent.layoutInflater, parent, false), itemTheme = mediaTypeItemsTheme?.mediaTypeItem, @@ -119,6 +125,12 @@ internal class EntryWidgetAdapter( holder.bind(item, item.value) { onItemClickListener?.invoke(item) } + } else if (item is EntryWidgetContract.ItemType.MessagingOngoing && + holder is EntryWidgetMessagingItemViewHolder + ) { + holder.bind(item, item.value) { + onItemClickListener?.invoke(item) + } } else { holder.bind(item) { onItemClickListener?.invoke(item) @@ -133,7 +145,9 @@ internal class EntryWidgetAdapter( EntryWidgetContract.ItemType.SdkNotInitializedState, EntryWidgetContract.ItemType.ErrorState -> ViewType.ERROR_ITEM.ordinal EntryWidgetContract.ItemType.PoweredBy -> ViewType.PROVIDED_BY_ITEM.ordinal - is EntryWidgetContract.ItemType.Messaging -> ViewType.MESSAGING_MEDIA_TYPE_ITEM.ordinal + is EntryWidgetContract.ItemType.Messaging, + is EntryWidgetContract.ItemType.MessagingOngoing -> ViewType.MESSAGING_MEDIA_TYPE_ITEM.ordinal + is EntryWidgetContract.ItemType.CallVisualizerOngoing -> ViewType.CALL_VISUALIZER_ITEM.ordinal else -> ViewType.LIVE_MEDIA_TYPE_ITEMS.ordinal } } diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetCallVisualizerItemViewHolder.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetCallVisualizerItemViewHolder.kt new file mode 100644 index 000000000..c7ae5dbcf --- /dev/null +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetCallVisualizerItemViewHolder.kt @@ -0,0 +1,46 @@ +package com.glia.widgets.entrywidget.adapter + +import android.view.View +import androidx.core.view.isVisible +import com.glia.widgets.R +import com.glia.widgets.databinding.EntryWidgetCallVisualizerItemBinding +import com.glia.widgets.entrywidget.EntryWidgetContract +import com.glia.widgets.helper.setLocaleHint +import com.glia.widgets.helper.setLocaleText +import com.glia.widgets.view.unifiedui.applyImageColorTheme +import com.glia.widgets.view.unifiedui.applyLayerTheme +import com.glia.widgets.view.unifiedui.applyTextTheme +import com.glia.widgets.view.unifiedui.theme.entrywidget.MediaTypeItemTheme + +internal class EntryWidgetCallVisualizerItemViewHolder( + private val binding: EntryWidgetCallVisualizerItemBinding, + itemTheme: MediaTypeItemTheme?, +) : EntryWidgetAdapter.ViewHolder(binding.root) { + + init { + itemTheme?.let { + binding.root.applyLayerTheme(it.background) + binding.title.applyTextTheme(it.title) + binding.description.applyTextTheme(it.message) + binding.icon.applyImageColorTheme(it.iconColor) + it.loadingTintColor?.primaryColorStateList?.let { tintList -> + binding.iconLoading.backgroundTintList = tintList + binding.titleLoading.backgroundTintList = tintList + binding.descriptionLoading.backgroundTintList = tintList + } + } + } + + override fun bind( + itemType: EntryWidgetContract.ItemType, + onClickListener: View.OnClickListener + ) { + binding.root.setOnClickListener(onClickListener) + binding.root.contentDescription = null + binding.icon.setImageResource(R.drawable.ic_screensharing) + binding.title.setLocaleText(R.string.entry_widget_call_visualizer_button_label) + binding.loadingGroup.isVisible = itemType == EntryWidgetContract.ItemType.LoadingState + binding.description.setLocaleText(R.string.entry_widget_call_visualizer_description) + binding.description.setLocaleHint(R.string.entry_widget_ongoing_engagement_button_accessibility_hint) + } +} diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetItemDivider.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetItemDivider.kt index 22eeef354..de2de1ff5 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetItemDivider.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetItemDivider.kt @@ -58,6 +58,7 @@ internal class EntryWidgetItemDivider( private fun isContactItem(viewType: Int?): Boolean { return viewType == EntryWidgetAdapter.ViewType.LIVE_MEDIA_TYPE_ITEMS.ordinal || - viewType == EntryWidgetAdapter.ViewType.MESSAGING_MEDIA_TYPE_ITEM.ordinal + viewType == EntryWidgetAdapter.ViewType.MESSAGING_MEDIA_TYPE_ITEM.ordinal || + viewType == EntryWidgetAdapter.ViewType.CALL_VISUALIZER_ITEM.ordinal } } diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetLiveItemViewHolder.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetLiveItemViewHolder.kt index 1e16e4ec7..7809ffdbe 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetLiveItemViewHolder.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetLiveItemViewHolder.kt @@ -39,7 +39,7 @@ internal class EntryWidgetLiveItemViewHolder( } } - override fun bind(itemType: EntryWidgetContract.ItemType, onClickListener: View.OnClickListener) { + override fun bind(itemType: EntryWidgetContract.ItemType, onClickListener: View.OnClickListener) { // binding.root.setOnClickListener(onClickListener) binding.root.contentDescription = null when (itemType) { @@ -50,6 +50,13 @@ internal class EntryWidgetLiveItemViewHolder( binding.description.setLocaleHint(R.string.entry_widget_video_button_accessibility_hint) } + EntryWidgetContract.ItemType.VideoCallOngoing -> { + binding.icon.setImageResource(R.drawable.ic_video) + binding.title.setLocaleText(R.string.entry_widget_video_button_label) + binding.description.setLocaleText(R.string.entry_widget_ongoing_engagement_description) + binding.description.setLocaleHint(R.string.entry_widget_ongoing_engagement_button_accessibility_hint) + } + EntryWidgetContract.ItemType.AudioCall -> { binding.icon.setImageResource(R.drawable.ic_audio) binding.title.setLocaleText(R.string.entry_widget_audio_button_label) @@ -57,6 +64,13 @@ internal class EntryWidgetLiveItemViewHolder( binding.description.setLocaleHint(R.string.entry_widget_audio_button_accessibility_hint) } + EntryWidgetContract.ItemType.AudioCallOngoing -> { + binding.icon.setImageResource(R.drawable.ic_audio) + binding.title.setLocaleText(R.string.entry_widget_audio_button_label) + binding.description.setLocaleText(R.string.entry_widget_ongoing_engagement_description) + binding.description.setLocaleHint(R.string.entry_widget_ongoing_engagement_button_accessibility_hint) + } + EntryWidgetContract.ItemType.Chat -> { binding.icon.setImageResource(R.drawable.ic_chat) binding.title.setLocaleText(R.string.entry_widget_live_chat_button_label) @@ -64,6 +78,13 @@ internal class EntryWidgetLiveItemViewHolder( binding.description.setLocaleHint(R.string.entry_widget_live_chat_button_accessibility_hint) } + EntryWidgetContract.ItemType.ChatOngoing -> { + binding.icon.setImageResource(R.drawable.ic_chat) + binding.title.setLocaleText(R.string.entry_widget_live_chat_button_label) + binding.description.setLocaleText(R.string.entry_widget_ongoing_engagement_description) + binding.description.setLocaleHint(R.string.entry_widget_ongoing_engagement_button_accessibility_hint) + } + else -> { binding.icon.setImageResource(0) binding.title.text = null diff --git a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetMessagingItemViewHolder.kt b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetMessagingItemViewHolder.kt index 99636e740..98679999e 100644 --- a/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetMessagingItemViewHolder.kt +++ b/widgetssdk/src/main/java/com/glia/widgets/entrywidget/adapter/EntryWidgetMessagingItemViewHolder.kt @@ -53,8 +53,17 @@ internal class EntryWidgetMessagingItemViewHolder( binding.root.contentDescription = null binding.icon.setImageResource(R.drawable.ic_secure_message) binding.title.setLocaleText(R.string.entry_widget_secure_messaging_button_label) - binding.description.setLocaleText(R.string.entry_widget_secure_messaging_button_description) - binding.description.setLocaleHint(R.string.entry_widget_secure_messaging_button_accessibility_hint) binding.loadingGroup.isVisible = itemType == EntryWidgetContract.ItemType.LoadingState + + when (itemType) { + is EntryWidgetContract.ItemType.Messaging -> { + binding.description.setLocaleText(R.string.entry_widget_secure_messaging_button_description) + binding.description.setLocaleHint(R.string.entry_widget_secure_messaging_button_accessibility_hint) + } + else -> { + binding.description.setLocaleText(R.string.entry_widget_ongoing_engagement_description) + binding.description.setLocaleHint(R.string.entry_widget_ongoing_engagement_button_accessibility_hint) + } + } } } diff --git a/widgetssdk/src/main/res/layout/entry_widget_call_visualizer_item.xml b/widgetssdk/src/main/res/layout/entry_widget_call_visualizer_item.xml new file mode 100644 index 000000000..6566def2b --- /dev/null +++ b/widgetssdk/src/main/res/layout/entry_widget_call_visualizer_item.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + diff --git a/widgetssdk/src/main/res/values/new_strings.xml b/widgetssdk/src/main/res/values/new_strings.xml index 162039822..5c204e7a3 100644 --- a/widgetssdk/src/main/res/values/new_strings.xml +++ b/widgetssdk/src/main/res/values/new_strings.xml @@ -240,5 +240,9 @@ We couldn\'t load the contacts at this time. This may be due to a temporary syncing issue or network problem. Try again Loading indicator. Waiting for available options. + Ongoing • Tap to return + Returns to ongoing engagement + Call Visualizer + You are already in contact with the support team