Call transfer: prepare code for consult feature

This commit is contained in:
ganfra 2021-05-25 15:21:54 +02:00
parent a9c61dc309
commit 8eeae51cc6
8 changed files with 75 additions and 11 deletions

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.session.call
import java.util.UUID
object CallIdGenerator {
fun generate() = UUID.randomUUID().toString()
}

View file

@ -92,7 +92,10 @@ interface MxCall : MxCallDetail {
/**
* Send a m.call.replaces event to initiate call transfer.
*/
suspend fun transfer(targetUserId: String, targetRoomId: String?)
suspend fun transfer(targetUserId: String,
targetRoomId: String?,
createCallId: String?,
awaitCallId: String?)
fun addListener(listener: StateListener)
fun removeListener(listener: StateListener)

View file

@ -56,6 +56,9 @@ data class CallHangupContent(
@Json(name = "user_hangup")
USER_HANGUP,
@Json(name = "replaced")
REPLACED,
@Json(name = "user_media_failed")
USER_MEDIA_FAILED,

View file

@ -42,7 +42,7 @@ data class CallReplacesContent(
* (possibly waiting for user confirmation) and then continues the transfer in this room.
* If absent, the transferee contacts the Matrix User ID given in the target_user field in a room of its choosing.
*/
@Json(name = "target_room") val targerRoomId: String? = null,
@Json(name = "target_room") val targetRoomId: String? = null,
/**
* An object giving information about the transfer target
*/

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.session.call
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.call.CallIdGenerator
import org.matrix.android.sdk.api.session.call.MxCall
import org.matrix.android.sdk.api.session.room.model.call.CallCapabilities
import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent
@ -63,7 +64,7 @@ internal class MxCallFactory @Inject constructor(
fun createOutgoingCall(roomId: String, opponentUserId: String, isVideoCall: Boolean): MxCall {
return MxCallImpl(
callId = UUID.randomUUID().toString(),
callId = CallIdGenerator.generate(),
isOutgoing = true,
roomId = roomId,
userId = userId,

View file

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.session.call.model
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.call.CallIdGenerator
import org.matrix.android.sdk.api.session.call.CallState
import org.matrix.android.sdk.api.session.call.MxCall
import org.matrix.android.sdk.api.session.events.model.Content
@ -202,7 +203,10 @@ internal class MxCallImpl(
.also { eventSenderProcessor.postEvent(it) }
}
override suspend fun transfer(targetUserId: String, targetRoomId: String?) {
override suspend fun transfer(targetUserId: String,
targetRoomId: String?,
createCallId: String?,
awaitCallId: String?) {
val profileInfoParams = GetProfileInfoTask.Params(targetUserId)
val profileInfo = try {
getProfileInfoTask.execute(profileInfoParams)
@ -213,15 +217,16 @@ internal class MxCallImpl(
CallReplacesContent(
callId = callId,
partyId = ourPartyId,
replacementId = UUID.randomUUID().toString(),
replacementId = CallIdGenerator.generate(),
version = MxCall.VOIP_PROTO_VERSION.toString(),
targetUser = CallReplacesContent.TargetUser(
id = targetUserId,
displayName = profileInfo?.get(ProfileService.DISPLAY_NAME_KEY) as? String,
avatarUrl = profileInfo?.get(ProfileService.AVATAR_URL_KEY) as? String
),
targerRoomId = targetRoomId,
createCall = UUID.randomUUID().toString()
targetRoomId = targetRoomId,
awaitCall = awaitCallId,
createCall = createCallId
)
.let { createEventAndLocalEcho(type = EventType.CALL_REPLACES, roomId = roomId, content = it.toContent()) }
.also { eventSenderProcessor.postEvent(it) }

View file

@ -75,7 +75,7 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
override fun handle(action: CallTransferAction) {
when (action) {
is CallTransferAction.ConnectWithUserId -> connectWithUserId(action)
is CallTransferAction.ConnectWithUserId -> connectWithUserId(action)
is CallTransferAction.ConnectWithPhoneNumber -> connectWithPhoneNumber(action)
}.exhaustive
}
@ -84,7 +84,7 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
viewModelScope.launch {
try {
_viewEvents.post(CallTransferViewEvents.Loading)
call?.mxCall?.transfer(action.selectedUserId, null)
call?.transferToUser(action.selectedUserId, null)
_viewEvents.post(CallTransferViewEvents.Dismiss)
} catch (failure: Throwable) {
_viewEvents.post(CallTransferViewEvents.FailToTransfer)
@ -97,7 +97,7 @@ class CallTransferViewModel @AssistedInject constructor(@Assisted initialState:
try {
_viewEvents.post(CallTransferViewEvents.Loading)
val result = dialPadLookup.lookupPhoneNumber(action.phoneNumber)
call?.mxCall?.transfer(result.userId, result.roomId)
call?.transferToUser(result.userId, result.roomId)
_viewEvents.post(CallTransferViewEvents.Dismiss)
} catch (failure: Throwable) {
_viewEvents.post(CallTransferViewEvents.FailToTransfer)

View file

@ -45,6 +45,7 @@ import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.call.CallIdGenerator
import org.matrix.android.sdk.api.session.call.CallState
import org.matrix.android.sdk.api.session.call.MxCall
import org.matrix.android.sdk.api.session.call.MxPeerConnectionState
@ -268,7 +269,7 @@ class WebRtcCall(val mxCall: MxCall,
sessionScope?.launch(dispatcher) {
when (mode) {
VectorCallActivity.INCOMING_ACCEPT -> {
VectorCallActivity.INCOMING_ACCEPT -> {
internalAcceptIncomingCall()
}
VectorCallActivity.INCOMING_RINGING -> {
@ -286,6 +287,34 @@ class WebRtcCall(val mxCall: MxCall,
}
}
suspend fun transferToUser(targetUserId: String, targetRoomId: String?) {
mxCall.transfer(
targetUserId = targetUserId,
targetRoomId = targetRoomId,
createCallId = CallIdGenerator.generate(),
awaitCallId = null
)
endCall(true, CallHangupContent.Reason.REPLACED)
}
suspend fun transferToCall(transferTargetCall: WebRtcCall) {
val newCallId = CallIdGenerator.generate()
transferTargetCall.mxCall.transfer(
targetUserId = this.mxCall.opponentUserId,
targetRoomId = null,
createCallId = null,
awaitCallId = newCallId
)
this.mxCall.transfer(
transferTargetCall.mxCall.opponentUserId,
targetRoomId = null,
createCallId = newCallId,
awaitCallId = null
)
endCall(true, CallHangupContent.Reason.REPLACED)
transferTargetCall.endCall(true, CallHangupContent.Reason.REPLACED)
}
fun acceptIncomingCall() {
sessionScope?.launch {
Timber.v("## VOIP acceptIncomingCall from state ${mxCall.state}")