From 5c1bf925143bdae8484c8ad3a0b3753545b4e1b4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 13 Jul 2021 10:44:34 +0200 Subject: [PATCH] WebRtcCall: start using PiP --- vector/src/main/AndroidManifest.xml | 4 + .../app/features/call/VectorCallActivity.kt | 92 ++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index e71f355a23..87f1a9ac82 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -270,7 +270,11 @@ android:name=".features.attachments.preview.AttachmentsPreviewActivity" android:theme="@style/Theme.Vector.Black.AttachmentsPreview" /> (), CallContro override fun getMenuRes() = R.menu.vector_call + override fun onUserLeaveHint() { + enterPictureInPictureIfRequired() + } + + override fun onBackPressed() { + if (!enterPictureInPictureIfRequired()) { + super.onBackPressed() + } + } + + private fun enterPictureInPictureIfRequired(): Boolean = withState(callViewModel) { + if (!it.isVideoCall) { + false + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val aspectRatio = Rational(resources.getDimensionPixelSize(R.dimen.call_pip_width), resources.getDimensionPixelSize(R.dimen.call_pip_height)) + val params = PictureInPictureParams.Builder() + .setAspectRatio(aspectRatio) + .build() + renderPiPMode(it) + enterPictureInPictureMode(params) + } else { + false + } + } + + private fun isInPictureInPictureModeSafe(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode + } + + override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) = withState(callViewModel) { + renderState(it) + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.menu_call_open_chat) { returnToChat() return true + } else if (item.itemId == android.R.id.home) { + // We check here as we want PiP in some cases + onBackPressed() + return true } return super.onOptionsItemSelected(item) } @@ -182,7 +222,17 @@ class VectorCallActivity : VectorBaseActivity(), CallContro finish() return } + if (isInPictureInPictureModeSafe()) { + renderPiPMode(state) + } else { + renderFullScreenMode(state) + } + } + private fun renderFullScreenMode(state: VectorCallViewState) { + views.callToolbar.isVisible = true + views.callControlsView.isVisible = true + views.pipRendererWrapper.isVisible = true views.callControlsView.updateForState(state) val callState = state.callState.invoke() views.callActionText.setOnClickListener(null) @@ -260,6 +310,46 @@ class VectorCallActivity : VectorBaseActivity(), CallContro } } + private fun renderPiPMode(state: VectorCallViewState) { + val callState = state.callState.invoke() + views.callToolbar.isVisible = false + views.callControlsView.isVisible = false + views.pipRendererWrapper.isVisible = false + views.pipRenderer.isVisible = false + when (callState) { + is CallState.Idle, + is CallState.CreateOffer, + is CallState.LocalRinging, + is CallState.Dialing, + is CallState.Answering -> { + views.fullscreenRenderer.isVisible = false + views.callInfoGroup.isVisible = false + // showLoading() + } + is CallState.Connected -> { + if (callState.iceConnectionState == MxPeerConnectionState.CONNECTED) { + if (state.isLocalOnHold || state.isRemoteOnHold) { + views.smallIsHeldIcon.isVisible = true + views.fullscreenRenderer.isVisible = false + views.callInfoGroup.isVisible = true + configureCallInfo(state, blurAvatar = true) + } else { + configureCallInfo(state) + views.fullscreenRenderer.isVisible = true + views.callInfoGroup.isVisible = false + } + } else { + //showLoading() + } + } + is CallState.Terminated -> { + finish() + } + null -> { + } + } + } + private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) { state.callInfo?.opponentUserItem?.let { val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen_blur) @@ -280,7 +370,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro avatarRenderer.render(it, views.otherMemberAvatar) } } - if (state.otherKnownCallInfo?.opponentUserItem == null) { + if (state.otherKnownCallInfo?.opponentUserItem == null || isInPictureInPictureModeSafe()) { views.otherKnownCallLayout.isVisible = false } else { val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId)