VoIP: update in call ui (blur)

This commit is contained in:
ganfra 2020-12-01 17:50:59 +01:00
parent 8f5a11493b
commit 4a3f0c8898
4 changed files with 52 additions and 22 deletions

View File

@ -118,6 +118,9 @@ android {
targetSdkVersion 29 targetSdkVersion 29
multiDexEnabled true multiDexEnabled true
renderscriptTargetApi 24
renderscriptSupportModeEnabled true
// `develop` branch will have version code from timestamp, to ensure each build from CI has a incremented versionCode. // `develop` branch will have version code from timestamp, to ensure each build from CI has a incremented versionCode.
// Other branches (master, features, etc.) will have version code based on application version. // Other branches (master, features, etc.) will have version code based on application version.
versionCode project.getVersionCode() versionCode project.getVersionCode()
@ -375,6 +378,7 @@ dependencies {
implementation 'com.google.android:flexbox:1.1.1' implementation 'com.google.android:flexbox:1.1.1'
implementation "androidx.autofill:autofill:$autofill_version" implementation "androidx.autofill:autofill:$autofill_version"
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta10' implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta10'
implementation 'jp.wasabeef:glide-transformations:4.3.0'
// Custom Tab // Custom Tab
implementation 'androidx.browser:browser:1.2.0' implementation 'androidx.browser:browser:1.2.0'

View File

@ -26,21 +26,17 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.widget.ImageView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import butterknife.BindView import butterknife.BindView
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.viewModel
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.glide.GlideApp
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.services.CallService import im.vector.app.core.services.CallService
import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL
@ -59,7 +55,6 @@ import org.matrix.android.sdk.api.session.call.CallState
import org.matrix.android.sdk.api.session.call.MxCallDetail import org.matrix.android.sdk.api.session.call.MxCallDetail
import org.matrix.android.sdk.api.session.call.MxPeerConnectionState import org.matrix.android.sdk.api.session.call.MxPeerConnectionState
import org.matrix.android.sdk.api.session.call.TurnServerResponse import org.matrix.android.sdk.api.session.call.TurnServerResponse
import org.matrix.android.sdk.api.util.MatrixItem
import org.webrtc.EglBase import org.webrtc.EglBase
import org.webrtc.RendererCommon import org.webrtc.RendererCommon
import org.webrtc.SurfaceViewRenderer import org.webrtc.SurfaceViewRenderer
@ -104,8 +99,6 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
private var rootEglBase: EglBase? = null private var rootEglBase: EglBase? = null
var systemUiVisibility = false
var surfaceRenderersAreInitialized = false var surfaceRenderersAreInitialized = false
override fun doBeforeSetContentView() { override fun doBeforeSetContentView() {
@ -113,13 +106,12 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
window.decorView.systemUiVisibility = ( window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
View.SYSTEM_UI_FLAG_LAYOUT_STABLE window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
window.statusBarColor = Color.TRANSPARENT
window.navigationBarColor = Color.TRANSPARENT
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
window.statusBarColor = Color.TRANSPARENT
window.navigationBarColor = Color.BLACK
super.onCreate(savedInstanceState)
if (intent.hasExtra(MvRx.KEY_ARG)) { if (intent.hasExtra(MvRx.KEY_ARG)) {
callArgs = intent.getParcelableExtra(MvRx.KEY_ARG)!! callArgs = intent.getParcelableExtra(MvRx.KEY_ARG)!!
@ -213,7 +205,7 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
smallIsHeldIcon.isVisible = true smallIsHeldIcon.isVisible = true
callVideoGroup.isInvisible = true callVideoGroup.isInvisible = true
callInfoGroup.isVisible = true callInfoGroup.isVisible = true
configureCallInfo(state) configureCallInfo(state, blurAvatar = true)
if (state.isRemoteOnHold) { if (state.isRemoteOnHold) {
callActionText.setText(R.string.call_resume_action) callActionText.setText(R.string.call_resume_action)
callActionText.isVisible = true callActionText.isVisible = true
@ -256,12 +248,18 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
} }
} }
private fun configureCallInfo(state: VectorCallViewState) { private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) {
state.otherUserMatrixItem.invoke()?.let { state.otherUserMatrixItem.invoke()?.let {
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
avatarRenderer.renderBlur(it, bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter)
participantNameText.text = it.getBestName() participantNameText.text = it.getBestName()
if (blurAvatar) {
avatarRenderer.renderBlur(it, otherMemberAvatar, sampling = 2, rounded = true, colorFilter = colorFilter)
} else {
avatarRenderer.render(it, otherMemberAvatar) avatarRenderer.render(it, otherMemberAvatar)
} }
} }
}
private fun configureCallViews() { private fun configureCallViews() {
callControlsView.interactionListener = this callControlsView.interactionListener = this
@ -289,7 +287,7 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
// Init Full Screen renderer // Init Full Screen renderer
fullscreenRenderer.init(rootEglBase!!.eglBaseContext, null) fullscreenRenderer.init(rootEglBase!!.eglBaseContext, null)
fullscreenRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT) fullscreenRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
pipRenderer.setZOrderMediaOverlay(true) pipRenderer.setZOrderMediaOverlay(true)
pipRenderer.setEnableHardwareScaler(true /* enabled */) pipRenderer.setEnableHardwareScaler(true /* enabled */)

View File

@ -20,9 +20,13 @@ import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.widget.ImageView import android.widget.ImageView
import androidx.annotation.AnyThread import androidx.annotation.AnyThread
import androidx.annotation.ColorInt
import androidx.annotation.UiThread import androidx.annotation.UiThread
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.TextDrawable
import com.bumptech.glide.load.MultiTransformation
import com.bumptech.glide.load.Transformation
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.DrawableImageViewTarget import com.bumptech.glide.request.target.DrawableImageViewTarget
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
@ -32,6 +36,8 @@ import im.vector.app.core.glide.GlideApp
import im.vector.app.core.glide.GlideRequest import im.vector.app.core.glide.GlideRequest
import im.vector.app.core.glide.GlideRequests import im.vector.app.core.glide.GlideRequests
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import jp.wasabeef.glide.transformations.BlurTransformation
import jp.wasabeef.glide.transformations.ColorFilterTransformation
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.content.ContentUrlResolver
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
@ -90,6 +96,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
target: Target<Drawable>) { target: Target<Drawable>) {
val placeholder = getPlaceholderDrawable(matrixItem) val placeholder = getPlaceholderDrawable(matrixItem)
buildGlideRequest(glideRequests, matrixItem.avatarUrl) buildGlideRequest(glideRequests, matrixItem.avatarUrl)
.apply(RequestOptions.circleCropTransform())
.placeholder(placeholder) .placeholder(placeholder)
.into(target) .into(target)
} }
@ -117,6 +124,22 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
.get() .get()
} }
@UiThread
fun renderBlur(matrixItem: MatrixItem, imageView: ImageView, sampling: Int, rounded: Boolean, @ColorInt colorFilter: Int? = null) {
val transformations = mutableListOf<Transformation<Bitmap>>(
BlurTransformation(20, sampling)
)
if (colorFilter != null) {
transformations.add(ColorFilterTransformation(colorFilter))
}
if (rounded) {
transformations.add(CircleCrop())
}
buildGlideRequest(GlideApp.with(imageView), matrixItem.avatarUrl)
.apply(RequestOptions.bitmapTransform(MultiTransformation(transformations)))
.into(imageView)
}
@AnyThread @AnyThread
fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem): Drawable { fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem): Drawable {
return buildGlideRequest(glideRequests, matrixItem.avatarUrl) return buildGlideRequest(glideRequests, matrixItem.avatarUrl)
@ -140,9 +163,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
private fun buildGlideRequest(glideRequests: GlideRequests, avatarUrl: String?): GlideRequest<Drawable> { private fun buildGlideRequest(glideRequests: GlideRequests, avatarUrl: String?): GlideRequest<Drawable> {
val resolvedUrl = resolvedUrl(avatarUrl) val resolvedUrl = resolvedUrl(avatarUrl)
return glideRequests return glideRequests.load(resolvedUrl)
.load(resolvedUrl)
.apply(RequestOptions.circleCropTransform())
} }
private fun resolvedUrl(avatarUrl: String?): String? { private fun resolvedUrl(avatarUrl: String?): String? {

View File

@ -12,6 +12,13 @@
android:background="@color/bg_call_screen" android:background="@color/bg_call_screen"
tools:ignore="MergeRootFrame"> tools:ignore="MergeRootFrame">
<ImageView
android:id="@+id/bgCallView"
tools:src="@tools:sample/avatars"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<org.webrtc.SurfaceViewRenderer <org.webrtc.SurfaceViewRenderer
android:id="@+id/fullscreen_video_view" android:id="@+id/fullscreen_video_view"
android:layout_width="match_parent" android:layout_width="match_parent"