VoIP : clean and add changelog

This commit is contained in:
ganfra 2021-06-02 11:07:05 +02:00
parent 0eca809b83
commit a421f37e70
11 changed files with 153 additions and 44 deletions

View file

@ -67,6 +67,4 @@ interface CallListener {
* Called when an asserted identity event is received
*/
fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent)
}

View file

@ -0,0 +1 @@
Adds support for receiving MSC3086 Asserted Identity events.

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.core.glide
import android.content.Context
import android.graphics.drawable.Drawable
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import im.vector.app.core.extensions.vectorComponent
import org.matrix.android.sdk.api.util.MatrixItem
data class AvatarPlaceholder(val matrixItem: MatrixItem)
class AvatarPlaceholderModelLoaderFactory(private val context: Context) : ModelLoaderFactory<AvatarPlaceholder, Drawable> {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<AvatarPlaceholder, Drawable> {
return AvatarPlaceholderModelLoader(context)
}
override fun teardown() {
// Is there something to do here?
}
}
class AvatarPlaceholderModelLoader(private val context: Context)
: ModelLoader<AvatarPlaceholder, Drawable> {
override fun buildLoadData(model: AvatarPlaceholder, width: Int, height: Int, options: Options): ModelLoader.LoadData<Drawable>? {
return ModelLoader.LoadData(ObjectKey(model), AvatarPlaceholderDataFetcher(context, model))
}
override fun handles(model: AvatarPlaceholder): Boolean {
return true
}
}
class AvatarPlaceholderDataFetcher(context: Context, private val data: AvatarPlaceholder)
: DataFetcher<Drawable> {
private val avatarRenderer = context.vectorComponent().avatarRenderer()
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in Drawable>) {
val avatarPlaceholder = avatarRenderer.getPlaceholderDrawable(data.matrixItem)
callback.onDataReady(avatarPlaceholder)
}
override fun cleanup() {
// NOOP
}
override fun cancel() {
// NOOP
}
override fun getDataClass(): Class<Drawable> {
return Drawable::class.java
}
override fun getDataSource(): DataSource {
return DataSource.LOCAL
}
}

View file

@ -17,6 +17,7 @@
package im.vector.app.core.glide
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.Log
import com.bumptech.glide.Glide
@ -40,5 +41,10 @@ class MyAppGlideModule : AppGlideModule() {
InputStream::class.java,
VectorGlideModelLoaderFactory(context)
)
registry.append(
AvatarPlaceholder::class.java,
Drawable::class.java,
AvatarPlaceholderModelLoaderFactory(context)
)
}
}

View file

@ -198,18 +198,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
}
is CallState.Connected -> {
if (callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
if (state.transferee !is VectorCallViewState.TransfereeState.NoTransferee) {
val transfereeName = if (state.transferee is VectorCallViewState.TransfereeState.KnownTransferee) {
state.transferee.name
} else {
getString(R.string.call_transfer_unknown_person)
}
views.callActionText.text = getString(R.string.call_transfer_transfer_to_title, transfereeName)
views.callActionText.isVisible = true
views.callActionText.setOnClickListener { callViewModel.handle(VectorCallViewActions.TransferCall) }
views.callStatusText.text = state.formattedDuration
configureCallInfo(state)
} else if (state.isLocalOnHold || state.isRemoteOnHold) {
if (state.isLocalOnHold || state.isRemoteOnHold) {
views.smallIsHeldIcon.isVisible = true
views.callVideoGroup.isInvisible = true
views.callInfoGroup.isVisible = true
@ -225,6 +214,17 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
views.callStatusText.text = getString(R.string.call_held_by_user, it.getBestName())
}
}
} else if (state.transferee !is VectorCallViewState.TransfereeState.NoTransferee) {
val transfereeName = if (state.transferee is VectorCallViewState.TransfereeState.KnownTransferee) {
state.transferee.name
} else {
getString(R.string.call_transfer_unknown_person)
}
views.callActionText.text = getString(R.string.call_transfer_transfer_to_title, transfereeName)
views.callActionText.isVisible = true
views.callActionText.setOnClickListener { callViewModel.handle(VectorCallViewActions.TransferCall) }
views.callStatusText.text = state.formattedDuration
configureCallInfo(state)
} else {
views.callStatusText.text = state.formattedDuration
configureCallInfo(state)
@ -256,15 +256,15 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) {
state.callInfo?.opponentUserItem?.let {
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter)
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen_blur)
avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter, addPlaceholder = false)
if (state.transferee is VectorCallViewState.TransfereeState.NoTransferee) {
views.participantNameText.text = it.getBestName()
} else {
views.participantNameText.text = getString(R.string.call_transfer_consulting_with, it.getBestName())
}
if (blurAvatar) {
avatarRenderer.renderBlur(it, views.otherMemberAvatar, sampling = 2, rounded = true, colorFilter = colorFilter)
avatarRenderer.renderBlur(it, views.otherMemberAvatar, sampling = 2, rounded = true, colorFilter = colorFilter, addPlaceholder = true)
} else {
avatarRenderer.render(it, views.otherMemberAvatar)
}
@ -273,13 +273,14 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
views.otherKnownCallLayout.isVisible = false
} else {
val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId)
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen_blur)
avatarRenderer.renderBlur(
matrixItem = state.otherKnownCallInfo.opponentUserItem,
imageView = views.otherKnownCallAvatarView,
sampling = 20,
rounded = false,
colorFilter = colorFilter
rounded = true,
colorFilter = colorFilter,
addPlaceholder = true
)
views.otherKnownCallLayout.isVisible = true
views.otherSmallIsHeldIcon.isVisible = otherCall?.let { it.isLocalOnHold || it.remoteOnHold }.orFalse()
@ -288,7 +289,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
private fun configureCallViews() {
views.callControlsView.interactionListener = this
views.otherKnownCallAvatarView.setOnClickListener {
views.otherKnownCallLayout.setOnClickListener {
withState(callViewModel) {
val otherCall = callManager.getCallById(it.otherKnownCallInfo?.callId ?: "") ?: return@withState
startActivity(newIntent(this, otherCall, null))

View file

@ -89,7 +89,7 @@ class VectorCallViewModel @AssistedInject constructor(
}
}
override fun assertedIdentityChanged(){
override fun assertedIdentityChanged() {
setState {
copy(callInfo = call?.extractCallInfo())
}
@ -208,17 +208,17 @@ class VectorCallViewModel @AssistedInject constructor(
}
}
private fun WebRtcCall.extractCallInfo(): VectorCallViewState.CallInfo{
private fun WebRtcCall.extractCallInfo(): VectorCallViewState.CallInfo {
val assertedIdentity = this.remoteAssertedIdentity
val matrixItem = if(assertedIdentity != null){
val matrixItem = if (assertedIdentity != null) {
val userId = if (MatrixPatterns.isUserId(assertedIdentity.id)) {
assertedIdentity.id!!
} else {
// Need an id starting with @
"@${assertedIdentity.displayName}"
}
MatrixItem.UserItem(userId,assertedIdentity.displayName, assertedIdentity.avatarUrl)
}else {
MatrixItem.UserItem(userId, assertedIdentity.displayName, assertedIdentity.avatarUrl)
} else {
getOpponentAsMatrixItem(session)
}
return VectorCallViewState.CallInfo(callId, matrixItem)

View file

@ -20,7 +20,6 @@ import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.call.audio.CallAudioManager
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.session.call.CallState
import org.matrix.android.sdk.api.util.MatrixItem
@ -54,7 +53,7 @@ data class VectorCallViewState(
data class CallInfo(
val callId: String,
val opponentUserItem: MatrixItem? = null,
val opponentUserItem: MatrixItem? = null
)
constructor(callArgs: CallArgs) : this(

View file

@ -424,7 +424,7 @@ class WebRtcCallManager @Inject constructor(
}
override fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
if(!BuildConfig.handleCallAssertedIdentityEvents){
if (!BuildConfig.handleCallAssertedIdentityEvents) {
return
}
val call = callsByCallId[callAssertedIdentityContent.callId]

View file

@ -34,6 +34,7 @@ import com.bumptech.glide.request.target.DrawableImageViewTarget
import com.bumptech.glide.request.target.Target
import im.vector.app.core.contacts.MappedContact
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.glide.AvatarPlaceholder
import im.vector.app.core.glide.GlideApp
import im.vector.app.core.glide.GlideRequest
import im.vector.app.core.glide.GlideRequests
@ -136,7 +137,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
matrixItem: MatrixItem,
target: Target<Drawable>) {
val placeholder = getPlaceholderDrawable(matrixItem)
buildGlideRequest(glideRequests, matrixItem.avatarUrl)
glideRequests.loadResolvedUrl(matrixItem.avatarUrl)
.apply {
when (matrixItem) {
is MatrixItem.SpaceItem -> {
@ -175,7 +176,12 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
}
@UiThread
fun renderBlur(matrixItem: MatrixItem, imageView: ImageView, sampling: Int, rounded: Boolean, @ColorInt colorFilter: Int? = null) {
fun renderBlur(matrixItem: MatrixItem,
imageView: ImageView,
sampling: Int,
rounded: Boolean,
@ColorInt colorFilter: Int? = null,
addPlaceholder: Boolean) {
val transformations = mutableListOf<Transformation<Bitmap>>(
BlurTransformation(20, sampling)
)
@ -185,14 +191,26 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
if (rounded) {
transformations.add(CircleCrop())
}
buildGlideRequest(GlideApp.with(imageView), matrixItem.avatarUrl)
.apply(RequestOptions.bitmapTransform(MultiTransformation(transformations)))
val bitmapTransform = RequestOptions.bitmapTransform(MultiTransformation(transformations))
val glideRequests = GlideApp.with(imageView)
val placeholderRequest = if (addPlaceholder) {
glideRequests
.load(AvatarPlaceholder(matrixItem))
.apply(bitmapTransform)
} else {
null
}
glideRequests.loadResolvedUrl(matrixItem.avatarUrl)
.apply(bitmapTransform)
// We are using thumbnail and error API so we can have blur transformation on it...
.thumbnail(placeholderRequest)
.error(placeholderRequest)
.into(imageView)
}
@AnyThread
fun getCachedDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem): Drawable {
return buildGlideRequest(glideRequests, matrixItem.avatarUrl)
return glideRequests.loadResolvedUrl(matrixItem.avatarUrl)
.onlyRetrieveFromCache(true)
.apply(RequestOptions.circleCropTransform())
.submit()
@ -220,9 +238,9 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
// PRIVATE API *********************************************************************************
private fun buildGlideRequest(glideRequests: GlideRequests, avatarUrl: String?): GlideRequest<Drawable> {
private fun GlideRequests.loadResolvedUrl(avatarUrl: String?): GlideRequest<Drawable> {
val resolvedUrl = resolvedUrl(avatarUrl)
return glideRequests.load(resolvedUrl)
return load(resolvedUrl)
}
private fun resolvedUrl(avatarUrl: String?): String? {

View file

@ -9,7 +9,7 @@
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_call_screen"
android:background="@color/bg_call_screen_blur"
tools:ignore="MergeRootFrame">
<ImageView
@ -37,23 +37,26 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
<androidx.cardview.widget.CardView
android:id="@+id/otherKnownCallLayout"
android:layout_width="80dp"
android:layout_height="144dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:background="@color/riotx_background_light"
android:visibility="gone"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
android:foreground="?attr/selectableItemBackground"
app:cardBackgroundColor="@color/bg_call_screen"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<ImageView
android:id="@+id/otherKnownCallAvatarView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?attr/selectableItemBackground"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center"
android:importantForAccessibility="no"
android:scaleType="centerCrop"
tools:src="@tools:sample/avatars" />
@ -66,7 +69,7 @@
android:importantForAccessibility="no"
android:src="@drawable/ic_call_small_pause" />
</FrameLayout>
</androidx.cardview.widget.CardView>
<ImageView
android:id="@+id/otherMemberAvatar"

View file

@ -127,7 +127,8 @@
<color name="riotx_positive_accent_alpha12">#1E0DBD8B</color>
<color name="riotx_button_disabled_alpha12">#1E61708B</color>
<color name="bg_call_screen">#99000000</color>
<color name="bg_call_screen_blur">#99000000</color>
<color name="bg_call_screen">#27303A</color>
<color name="riotx_notice">#FFFF4B55</color>
<color name="riotx_notice_secondary">#FF61708B</color>