mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Show error on connecting timeout + refactoring
This commit is contained in:
parent
c85ba51274
commit
fd3f591541
10 changed files with 167 additions and 171 deletions
|
@ -16,26 +16,29 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.call
|
||||
|
||||
enum class CallState {
|
||||
import org.webrtc.PeerConnection
|
||||
|
||||
sealed class CallState {
|
||||
|
||||
/** Idle, setting up objects */
|
||||
IDLE,
|
||||
object Idle : CallState()
|
||||
|
||||
/** Dialing. Outgoing call is signaling the remote peer */
|
||||
DIALING,
|
||||
object Dialing : CallState()
|
||||
|
||||
/** Local ringing. Incoming call offer received */
|
||||
LOCAL_RINGING,
|
||||
object LocalRinging : CallState()
|
||||
|
||||
/** Answering. Incoming call is responding to remote peer */
|
||||
ANSWERING,
|
||||
object Answering : CallState()
|
||||
|
||||
/** Connecting. Incoming/Outgoing Offer and answer are known, Currently checking and testing pairs of ice candidates */
|
||||
CONNECTING,
|
||||
|
||||
/** Connected. Incoming/Outgoing call, the call is connected */
|
||||
CONNECTED,
|
||||
/**
|
||||
* Connected. Incoming/Outgoing call, ice layer connecting or connected
|
||||
* Notice that the PeerState failed is not always final, if you switch network, new ice candidtates
|
||||
* could be exchanged, and the connection could go back to connected
|
||||
* */
|
||||
data class Connected(val iceConnectionState: PeerConnection.PeerConnectionState) : CallState()
|
||||
|
||||
/** Terminated. Incoming/Outgoing call, the call is terminated */
|
||||
TERMINATED,
|
||||
object Terminated : CallState()
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ internal class DefaultCallSignalingService @Inject constructor(
|
|||
override fun removeCallListener(listener: CallsListener) {
|
||||
callListeners.remove(listener)
|
||||
}
|
||||
|
||||
override fun getCallWithId(callId: String): MxCall? {
|
||||
Timber.v("## VOIP getCallWithId $callId all calls ${activeCalls.map { it.callId }}")
|
||||
return activeCalls.find { it.callId == callId }
|
||||
|
@ -189,25 +190,4 @@ internal class DefaultCallSignalingService @Inject constructor(
|
|||
companion object {
|
||||
const val CALL_TIMEOUT_MS = 120_000
|
||||
}
|
||||
|
||||
// internal class PeerSignalingClientFactory @Inject constructor(
|
||||
// @UserId private val userId: String,
|
||||
// private val localEchoEventFactory: LocalEchoEventFactory,
|
||||
// private val sendEventTask: SendEventTask,
|
||||
// private val taskExecutor: TaskExecutor,
|
||||
// private val cryptoService: CryptoService
|
||||
// ) {
|
||||
//
|
||||
// fun create(roomId: String, callId: String): PeerSignalingClient {
|
||||
// return RoomPeerSignalingClient(
|
||||
// callID = callId,
|
||||
// roomId = roomId,
|
||||
// userId = userId,
|
||||
// localEchoEventFactory = localEchoEventFactory,
|
||||
// sendEventTask = sendEventTask,
|
||||
// taskExecutor = taskExecutor,
|
||||
// cryptoService = cryptoService
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ internal class MxCallImpl(
|
|||
private val roomEventSender: RoomEventSender
|
||||
) : MxCall {
|
||||
|
||||
override var state: CallState = CallState.IDLE
|
||||
override var state: CallState = CallState.Idle
|
||||
set(value) {
|
||||
field = value
|
||||
dispatchStateChange()
|
||||
|
@ -74,17 +74,17 @@ internal class MxCallImpl(
|
|||
|
||||
init {
|
||||
if (isOutgoing) {
|
||||
state = CallState.IDLE
|
||||
state = CallState.Idle
|
||||
} else {
|
||||
// because it's created on reception of an offer
|
||||
state = CallState.LOCAL_RINGING
|
||||
state = CallState.LocalRinging
|
||||
}
|
||||
}
|
||||
|
||||
override fun offerSdp(sdp: SessionDescription) {
|
||||
if (!isOutgoing) return
|
||||
Timber.v("## VOIP offerSdp $callId")
|
||||
state = CallState.DIALING
|
||||
state = CallState.Dialing
|
||||
CallInviteContent(
|
||||
callId = callId,
|
||||
lifetime = DefaultCallSignalingService.CALL_TIMEOUT_MS,
|
||||
|
@ -120,13 +120,13 @@ internal class MxCallImpl(
|
|||
)
|
||||
.let { createEventAndLocalEcho(type = EventType.CALL_HANGUP, roomId = roomId, content = it.toContent()) }
|
||||
.also { roomEventSender.sendEvent(it) }
|
||||
state = CallState.TERMINATED
|
||||
state = CallState.Terminated
|
||||
}
|
||||
|
||||
override fun accept(sdp: SessionDescription) {
|
||||
Timber.v("## VOIP accept $callId")
|
||||
if (isOutgoing) return
|
||||
state = CallState.ANSWERING
|
||||
state = CallState.Answering
|
||||
CallAnswerContent(
|
||||
callId = callId,
|
||||
answer = CallAnswerContent.Answer(sdp = sdp.description)
|
||||
|
|
|
@ -29,6 +29,7 @@ import butterknife.OnClick
|
|||
import im.vector.matrix.android.api.session.call.CallState
|
||||
import im.vector.riotx.R
|
||||
import kotlinx.android.synthetic.main.fragment_call_controls.view.*
|
||||
import org.webrtc.PeerConnection
|
||||
|
||||
class CallControlsView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
|
@ -99,28 +100,34 @@ class CallControlsView @JvmOverloads constructor(
|
|||
videoToggleIcon.setImageResource(if (state.isVideoEnabled) R.drawable.ic_video else R.drawable.ic_video_off)
|
||||
|
||||
when (callState) {
|
||||
CallState.IDLE,
|
||||
CallState.DIALING,
|
||||
CallState.CONNECTING,
|
||||
CallState.ANSWERING -> {
|
||||
is CallState.Idle,
|
||||
is CallState.Dialing,
|
||||
is CallState.Answering -> {
|
||||
ringingControls.isVisible = true
|
||||
ringingControlAccept.isVisible = false
|
||||
ringingControlDecline.isVisible = true
|
||||
connectedControls.isVisible = false
|
||||
}
|
||||
CallState.LOCAL_RINGING -> {
|
||||
is CallState.LocalRinging -> {
|
||||
ringingControls.isVisible = true
|
||||
ringingControlAccept.isVisible = true
|
||||
ringingControlDecline.isVisible = true
|
||||
connectedControls.isVisible = false
|
||||
}
|
||||
CallState.CONNECTED -> {
|
||||
ringingControls.isVisible = false
|
||||
connectedControls.isVisible = true
|
||||
iv_video_toggle.isVisible = state.isVideoCall
|
||||
is CallState.Connected -> {
|
||||
if (callState.iceConnectionState == PeerConnection.PeerConnectionState.CONNECTED) {
|
||||
ringingControls.isVisible = false
|
||||
connectedControls.isVisible = true
|
||||
iv_video_toggle.isVisible = state.isVideoCall
|
||||
} else {
|
||||
ringingControls.isVisible = true
|
||||
ringingControlAccept.isVisible = false
|
||||
ringingControlDecline.isVisible = true
|
||||
connectedControls.isVisible = false
|
||||
}
|
||||
}
|
||||
CallState.TERMINATED,
|
||||
null -> {
|
||||
is CallState.Terminated,
|
||||
null -> {
|
||||
ringingControls.isVisible = false
|
||||
connectedControls.isVisible = false
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.os.Parcelable
|
|||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -39,6 +40,7 @@ import com.jakewharton.rxbinding3.view.clicks
|
|||
import im.vector.matrix.android.api.session.call.CallState
|
||||
import im.vector.matrix.android.api.session.call.EglUtils
|
||||
import im.vector.matrix.android.api.session.call.MxCallDetail
|
||||
import im.vector.matrix.android.api.session.call.TurnServerResponse
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.di.ScreenComponent
|
||||
import im.vector.riotx.core.platform.VectorBaseActivity
|
||||
|
@ -54,6 +56,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
|||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.activity_call.*
|
||||
import org.webrtc.EglBase
|
||||
import org.webrtc.PeerConnection
|
||||
import org.webrtc.RendererCommon
|
||||
import org.webrtc.SurfaceViewRenderer
|
||||
import timber.log.Timber
|
||||
|
@ -66,8 +69,7 @@ data class CallArgs(
|
|||
val callId: String?,
|
||||
val participantUserId: String,
|
||||
val isIncomingCall: Boolean,
|
||||
val isVideoCall: Boolean,
|
||||
val autoAccept: Boolean
|
||||
val isVideoCall: Boolean
|
||||
) : Parcelable
|
||||
|
||||
class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionListener {
|
||||
|
@ -216,53 +218,6 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||
turnScreenOffAndKeyguardOn()
|
||||
}
|
||||
|
||||
// override fun onResume() {
|
||||
// super.onResume()
|
||||
// }
|
||||
//
|
||||
// override fun onStop() {
|
||||
// super.onStop()
|
||||
// when(callViewModel.call?.state) {
|
||||
// CallState.DIALING -> {
|
||||
// CallService.onIncomingCall(
|
||||
// this,
|
||||
// callArgs.isVideoCall,
|
||||
// callArgs.participantUserId,
|
||||
// callArgs.roomId,
|
||||
// "",
|
||||
// callArgs.callId ?: ""
|
||||
// )
|
||||
// }
|
||||
// CallState.LOCAL_RINGING -> {
|
||||
// CallService.onIncomingCall(
|
||||
// this,
|
||||
// callArgs.isVideoCall,
|
||||
// callArgs.participantUserId,
|
||||
// callArgs.roomId,
|
||||
// "",
|
||||
// callArgs.callId ?: ""
|
||||
// )
|
||||
// }
|
||||
// CallState.ANSWERING,
|
||||
// CallState.CONNECTING,
|
||||
// CallState.CONNECTED -> {
|
||||
// CallService.onPendingCall(
|
||||
// this,
|
||||
// callArgs.isVideoCall,
|
||||
// callArgs.participantUserId,
|
||||
// callArgs.roomId,
|
||||
// "",
|
||||
// callArgs.callId ?: ""
|
||||
// )
|
||||
// }
|
||||
// CallState.TERMINATED ,
|
||||
// CallState.IDLE ,
|
||||
// null -> {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun renderState(state: VectorCallViewState) {
|
||||
Timber.v("## VOIP renderState call $state")
|
||||
if (state.callState is Fail) {
|
||||
|
@ -273,52 +228,55 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||
}
|
||||
|
||||
callControlsView.updateForState(state)
|
||||
when (state.callState.invoke()) {
|
||||
CallState.IDLE,
|
||||
CallState.DIALING -> {
|
||||
val callState = state.callState.invoke()
|
||||
when (callState) {
|
||||
is CallState.Idle,
|
||||
is CallState.Dialing -> {
|
||||
callVideoGroup.isInvisible = true
|
||||
callInfoGroup.isVisible = true
|
||||
callStatusText.setText(R.string.call_ring)
|
||||
configureCallInfo(state)
|
||||
}
|
||||
|
||||
CallState.LOCAL_RINGING -> {
|
||||
is CallState.LocalRinging -> {
|
||||
callVideoGroup.isInvisible = true
|
||||
callInfoGroup.isVisible = true
|
||||
callStatusText.text = null
|
||||
configureCallInfo(state)
|
||||
}
|
||||
|
||||
CallState.ANSWERING -> {
|
||||
is CallState.Answering -> {
|
||||
callVideoGroup.isInvisible = true
|
||||
callInfoGroup.isVisible = true
|
||||
callStatusText.setText(R.string.call_connecting)
|
||||
configureCallInfo(state)
|
||||
}
|
||||
CallState.CONNECTING -> {
|
||||
callVideoGroup.isInvisible = true
|
||||
callInfoGroup.isVisible = true
|
||||
configureCallInfo(state)
|
||||
callStatusText.setText(R.string.call_connecting)
|
||||
}
|
||||
CallState.CONNECTED -> {
|
||||
if (callArgs.isVideoCall) {
|
||||
callVideoGroup.isVisible = true
|
||||
callInfoGroup.isVisible = false
|
||||
pip_video_view.isVisible = !state.isVideoCaptureInError
|
||||
is CallState.Connected -> {
|
||||
if (callState.iceConnectionState == PeerConnection.PeerConnectionState.CONNECTED) {
|
||||
if (callArgs.isVideoCall) {
|
||||
callVideoGroup.isVisible = true
|
||||
callInfoGroup.isVisible = false
|
||||
pip_video_view.isVisible = !state.isVideoCaptureInError
|
||||
} else {
|
||||
callVideoGroup.isInvisible = true
|
||||
callInfoGroup.isVisible = true
|
||||
configureCallInfo(state)
|
||||
callStatusText.text = null
|
||||
}
|
||||
} else {
|
||||
// This state is not final, if you change network, new candidates will be sent
|
||||
callVideoGroup.isInvisible = true
|
||||
callInfoGroup.isVisible = true
|
||||
configureCallInfo(state)
|
||||
callStatusText.text = null
|
||||
callStatusText.setText(R.string.call_connecting)
|
||||
}
|
||||
// ensure all attached?
|
||||
peerConnectionManager.attachViewRenderers(pipRenderer, fullscreenRenderer, null)
|
||||
}
|
||||
CallState.TERMINATED -> {
|
||||
is CallState.Terminated -> {
|
||||
finish()
|
||||
}
|
||||
null -> {
|
||||
null -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -382,20 +340,29 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||
private fun handleViewEvents(event: VectorCallViewEvents?) {
|
||||
Timber.v("## VOIP handleViewEvents $event")
|
||||
when (event) {
|
||||
VectorCallViewEvents.DismissNoCall -> {
|
||||
VectorCallViewEvents.DismissNoCall -> {
|
||||
CallService.onNoActiveCall(this)
|
||||
finish()
|
||||
}
|
||||
null -> {
|
||||
is VectorCallViewEvents.ConnectionTimout -> {
|
||||
onErrorTimoutConnect(event.turn)
|
||||
}
|
||||
null -> {
|
||||
}
|
||||
}
|
||||
// when (event) {
|
||||
// is VectorCallViewEvents.CallAnswered -> {
|
||||
// }
|
||||
// is VectorCallViewEvents.CallHangup -> {
|
||||
// finish()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private fun onErrorTimoutConnect(turn: TurnServerResponse?) {
|
||||
Timber.d("## VOIP onErrorTimoutConnect $turn")
|
||||
// TODO ask to use default stun, etc...
|
||||
AlertDialog
|
||||
.Builder(this)
|
||||
.setTitle(R.string.call_failed_no_connection)
|
||||
.setMessage(getString(R.string.call_failed_no_connection_description))
|
||||
.setNegativeButton(R.string.ok) { _, _ ->
|
||||
callViewModel.handle(VectorCallViewActions.EndCall)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -411,7 +378,7 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||
return Intent(context, VectorCallActivity::class.java).apply {
|
||||
// what could be the best flags?
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
putExtra(MvRx.KEY_ARG, CallArgs(mxCall.roomId, mxCall.callId, mxCall.otherUserId, !mxCall.isOutgoing, mxCall.isVideoCall, false))
|
||||
putExtra(MvRx.KEY_ARG, CallArgs(mxCall.roomId, mxCall.callId, mxCall.otherUserId, !mxCall.isOutgoing, mxCall.isVideoCall))
|
||||
putExtra(EXTRA_MODE, OUTGOING_CREATED)
|
||||
}
|
||||
}
|
||||
|
@ -422,12 +389,11 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||
otherUserId: String,
|
||||
isIncomingCall: Boolean,
|
||||
isVideoCall: Boolean,
|
||||
accept: Boolean,
|
||||
mode: String?): Intent {
|
||||
return Intent(context, VectorCallActivity::class.java).apply {
|
||||
// what could be the best flags?
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
putExtra(MvRx.KEY_ARG, CallArgs(roomId, callId, otherUserId, isIncomingCall, isVideoCall, accept))
|
||||
putExtra(MvRx.KEY_ARG, CallArgs(roomId, callId, otherUserId, isIncomingCall, isVideoCall))
|
||||
putExtra(EXTRA_MODE, mode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,15 +26,20 @@ import com.airbnb.mvrx.Uninitialized
|
|||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.call.CallState
|
||||
import im.vector.matrix.android.api.session.call.MxCall
|
||||
import im.vector.matrix.android.api.session.call.TurnServerResponse
|
||||
import im.vector.matrix.android.api.util.MatrixItem
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewEvents
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||
import org.webrtc.PeerConnection
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
|
||||
data class VectorCallViewState(
|
||||
val callId: String? = null,
|
||||
|
@ -60,6 +65,7 @@ sealed class VectorCallViewActions : VectorViewModelAction {
|
|||
sealed class VectorCallViewEvents : VectorViewEvents {
|
||||
|
||||
object DismissNoCall : VectorCallViewEvents()
|
||||
data class ConnectionTimout(val turn: TurnServerResponse?) : VectorCallViewEvents()
|
||||
// data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents()
|
||||
// data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents()
|
||||
// object CallAccepted : VectorCallViewEvents()
|
||||
|
@ -72,15 +78,38 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
val webRtcPeerConnectionManager: WebRtcPeerConnectionManager
|
||||
) : VectorViewModel<VectorCallViewState, VectorCallViewActions, VectorCallViewEvents>(initialState) {
|
||||
|
||||
var autoReplyIfNeeded: Boolean = false
|
||||
|
||||
var call: MxCall? = null
|
||||
|
||||
var connectionTimoutTimer: Timer? = null
|
||||
|
||||
private val callStateListener = object : MxCall.StateListener {
|
||||
override fun onStateUpdate(call: MxCall) {
|
||||
val callState = call.state
|
||||
if (callState is CallState.Connected && callState.iceConnectionState == PeerConnection.PeerConnectionState.CONNECTED) {
|
||||
connectionTimoutTimer?.cancel()
|
||||
connectionTimoutTimer = null
|
||||
} else {
|
||||
// do we reset as long as it's moving?
|
||||
connectionTimoutTimer?.cancel()
|
||||
connectionTimoutTimer = Timer().apply {
|
||||
schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
session.callSignalingService().getTurnServer(object : MatrixCallback<TurnServerResponse> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
_viewEvents.post(VectorCallViewEvents.ConnectionTimout(null))
|
||||
}
|
||||
|
||||
override fun onSuccess(data: TurnServerResponse) {
|
||||
_viewEvents.post(VectorCallViewEvents.ConnectionTimout(data))
|
||||
}
|
||||
})
|
||||
}
|
||||
}, 30_000)
|
||||
}
|
||||
}
|
||||
setState {
|
||||
copy(
|
||||
callState = Success(call.state)
|
||||
callState = Success(callState)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -99,8 +128,6 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
|
||||
init {
|
||||
|
||||
autoReplyIfNeeded = args.autoAccept
|
||||
|
||||
initialState.callId?.let {
|
||||
|
||||
webRtcPeerConnectionManager.addCurrentCallListener(currentCallListener)
|
||||
|
|
|
@ -269,7 +269,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
|
||||
// The call is going to resume from background, we can reduce notif
|
||||
currentCall?.mxCall
|
||||
?.takeIf { it.state == CallState.CONNECTING || it.state == CallState.CONNECTED }
|
||||
?.takeIf { it.state is CallState.Connected }
|
||||
?.let { mxCall ->
|
||||
val name = sessionHolder.getSafeActiveSession()?.getUser(mxCall.otherUserId)?.getBestName()
|
||||
?: mxCall.roomId
|
||||
|
@ -466,7 +466,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
fun acceptIncomingCall() {
|
||||
Timber.v("## VOIP acceptIncomingCall from state ${currentCall?.mxCall?.state}")
|
||||
val mxCall = currentCall?.mxCall
|
||||
if (mxCall?.state == CallState.LOCAL_RINGING) {
|
||||
if (mxCall?.state == CallState.LocalRinging) {
|
||||
getTurnServer { turnServer ->
|
||||
internalAcceptIncomingCall(currentCall!!, turnServer)
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
fun detachRenderers() {
|
||||
// The call is going to continue in background, so ensure notification is visible
|
||||
currentCall?.mxCall
|
||||
?.takeIf { it.state == CallState.CONNECTING || it.state == CallState.CONNECTED }
|
||||
?.takeIf { it.state is CallState.Connected }
|
||||
?.let { mxCall ->
|
||||
// Start background service with notification
|
||||
|
||||
|
@ -687,7 +687,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
if (call.mxCall.callId != callHangupContent.callId) return Unit.also {
|
||||
Timber.w("onCallHangupReceived for non active call? ${callHangupContent.callId}")
|
||||
}
|
||||
call.mxCall.state = CallState.TERMINATED
|
||||
call.mxCall.state = CallState.Terminated
|
||||
currentCall = null
|
||||
close()
|
||||
}
|
||||
|
@ -702,7 +702,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
* or is closed (state "closed"); in addition, at least one transport is either "connected" or "completed"
|
||||
*/
|
||||
PeerConnection.PeerConnectionState.CONNECTED -> {
|
||||
callContext.mxCall.state = CallState.CONNECTED
|
||||
callContext.mxCall.state = CallState.Connected(newState)
|
||||
}
|
||||
/**
|
||||
* One or more of the ICE transports on the connection is in the "failed" state.
|
||||
|
@ -710,6 +710,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
PeerConnection.PeerConnectionState.FAILED -> {
|
||||
// This can be temporary, e.g when other ice not yet received...
|
||||
// callContext.mxCall.state = CallState.ERROR
|
||||
callContext.mxCall.state = CallState.Connected(newState)
|
||||
}
|
||||
/**
|
||||
* At least one of the connection's ICE transports (RTCIceTransports or RTCDtlsTransports) are in the "new" state,
|
||||
|
@ -723,20 +724,20 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
* that is, their RTCIceConnectionState is either "checking" or "connected", and no transports are in the "failed" state
|
||||
*/
|
||||
PeerConnection.PeerConnectionState.CONNECTING -> {
|
||||
callContext.mxCall.state = CallState.CONNECTING
|
||||
callContext.mxCall.state = CallState.Connected(PeerConnection.PeerConnectionState.CONNECTING)
|
||||
}
|
||||
/**
|
||||
* The RTCPeerConnection is closed.
|
||||
* This value was in the RTCSignalingState enum (and therefore found by reading the value of the signalingState)
|
||||
* property until the May 13, 2016 draft of the specification.
|
||||
*/
|
||||
PeerConnection.PeerConnectionState.CLOSED -> {
|
||||
}
|
||||
/**
|
||||
* At least one of the ICE transports for the connection is in the "disconnected" state and none of
|
||||
* the other transports are in the state "failed", "connecting", or "checking".
|
||||
*/
|
||||
PeerConnection.PeerConnectionState.CLOSED,
|
||||
/**
|
||||
* At least one of the ICE transports for the connection is in the "disconnected" state and none of
|
||||
* the other transports are in the state "failed", "connecting", or "checking".
|
||||
*/
|
||||
PeerConnection.PeerConnectionState.DISCONNECTED -> {
|
||||
callContext.mxCall.state = CallState.Connected(newState)
|
||||
}
|
||||
null -> {
|
||||
}
|
||||
|
|
|
@ -296,7 +296,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
sharedCallActionViewModel
|
||||
.activeCall
|
||||
.observe(viewLifecycleOwner, Observer {
|
||||
val hasActiveCall = it?.state == CallState.CONNECTED
|
||||
val hasActiveCall = it?.state is CallState.Connected
|
||||
activeCallView.isVisible = hasActiveCall
|
||||
})
|
||||
|
||||
|
@ -1517,14 +1517,13 @@ class RoomDetailFragment @Inject constructor(
|
|||
override fun onTapToReturnToCall() {
|
||||
sharedCallActionViewModel.activeCall.value?.let { call ->
|
||||
VectorCallActivity.newIntent(
|
||||
requireContext(),
|
||||
call.callId,
|
||||
call.roomId,
|
||||
call.otherUserId,
|
||||
!call.isOutgoing,
|
||||
call.isVideoCall,
|
||||
false,
|
||||
null
|
||||
context = requireContext(),
|
||||
callId = call.callId,
|
||||
roomId = call.roomId,
|
||||
otherUserId = call.otherUserId,
|
||||
isIncomingCall = !call.isOutgoing,
|
||||
isVideoCall = call.isVideoCall,
|
||||
mode = null
|
||||
).let {
|
||||
startActivity(it)
|
||||
}
|
||||
|
|
|
@ -293,30 +293,34 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
|||
// val pendingIntent = stackBuilder.getPendingIntent(requestId, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val contentIntent = VectorCallActivity.newIntent(
|
||||
context, callId, roomId, otherUserId, true, isVideo,
|
||||
false, VectorCallActivity.INCOMING_RINGING
|
||||
context = context,
|
||||
callId = callId,
|
||||
roomId = roomId,
|
||||
otherUserId = otherUserId,
|
||||
isIncomingCall = true,
|
||||
isVideoCall = isVideo,
|
||||
mode = VectorCallActivity.INCOMING_RINGING
|
||||
).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
data = Uri.parse("foobar://$callId")
|
||||
}
|
||||
val contentPendingIntent = PendingIntent.getActivity(context, System.currentTimeMillis().toInt(), contentIntent, 0)
|
||||
|
||||
// val contentPendingIntent = TaskStackBuilder.create(context)
|
||||
// .addNextIntentWithParentStack(Intent(context, HomeActivity::class.java))
|
||||
// .addNextIntent(RoomDetailActivity.newIntent(context, RoomDetailArgs(roomId = roomId))
|
||||
// .addNextIntent(VectorCallActivity.newIntent(context, callId, roomId, otherUserId, true, isVideo, false, VectorCallActivity.INCOMING_RINGING))
|
||||
// .getPendingIntent(System.currentTimeMillis().toInt(), PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val answerCallPendingIntent = TaskStackBuilder.create(context)
|
||||
.addNextIntentWithParentStack(Intent(context, HomeActivity::class.java))
|
||||
.addNextIntent(VectorCallActivity.newIntent(context, callId, roomId, otherUserId, true, isVideo, true, VectorCallActivity.INCOMING_ACCEPT))
|
||||
.addNextIntent(VectorCallActivity.newIntent(
|
||||
context = context,
|
||||
callId = callId,
|
||||
roomId = roomId,
|
||||
otherUserId = otherUserId,
|
||||
isIncomingCall = true,
|
||||
isVideoCall = isVideo,
|
||||
mode = VectorCallActivity.INCOMING_ACCEPT)
|
||||
)
|
||||
.getPendingIntent(System.currentTimeMillis().toInt(), PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
// val answerCallActionReceiver = Intent(context, CallHeadsUpActionReceiver::class.java).apply {
|
||||
// putExtra(CallHeadsUpService.EXTRA_CALL_ACTION_KEY, CallHeadsUpService.CALL_ACTION_ANSWER)
|
||||
// }
|
||||
val rejectCallActionReceiver = Intent(context, CallHeadsUpActionReceiver::class.java).apply {
|
||||
// putExtra(CallHeadsUpService.EXTRA_CALL_ACTION_KEY, CallHeadsUpService.CALL_ACTION_REJECT)
|
||||
putExtra(CallHeadsUpActionReceiver.EXTRA_CALL_ACTION_KEY, CallHeadsUpActionReceiver.CALL_ACTION_REJECT)
|
||||
}
|
||||
// val answerCallPendingIntent = PendingIntent.getBroadcast(context, requestId, answerCallActionReceiver, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val rejectCallPendingIntent = PendingIntent.getBroadcast(
|
||||
|
@ -367,8 +371,13 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
|||
val requestId = Random.nextInt(1000)
|
||||
|
||||
val contentIntent = VectorCallActivity.newIntent(
|
||||
context, callId, roomId, otherUserId, true, isVideo,
|
||||
false, null).apply {
|
||||
context = context,
|
||||
callId = callId,
|
||||
roomId = roomId,
|
||||
otherUserId = otherUserId,
|
||||
isIncomingCall = true,
|
||||
isVideoCall = isVideo,
|
||||
mode = null).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
data = Uri.parse("foobar://$callId")
|
||||
}
|
||||
|
@ -451,7 +460,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
|||
val contentPendingIntent = TaskStackBuilder.create(context)
|
||||
.addNextIntentWithParentStack(Intent(context, HomeActivity::class.java))
|
||||
// TODO other userId
|
||||
.addNextIntent(VectorCallActivity.newIntent(context, callId, roomId, "otherUserId", true, isVideo, false, null))
|
||||
.addNextIntent(VectorCallActivity.newIntent(context, callId, roomId, "otherUserId", true, isVideo, null))
|
||||
.getPendingIntent(System.currentTimeMillis().toInt(), PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
builder.setContentIntent(contentPendingIntent)
|
||||
|
|
|
@ -210,6 +210,10 @@
|
|||
<string name="call_failed_no_ice_description">Please ask the administrator of your homeserver (%1$s) to configure a TURN server in order for calls to work reliably.\n\nAlternatively, you can try to use the public server at %2$s, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings."</string>
|
||||
<string name="call_failed_no_ice_use_alt">Try using %s</string>
|
||||
<string name="call_failed_dont_ask_again">Do not ask me again</string>
|
||||
|
||||
<string name="call_failed_no_connection">RiotX Call Failed</string>
|
||||
<string name="call_failed_no_connection_description">Failed to establish real time connection.\nPlease ask the administrator of your homeserver to configure a TURN server in order for calls to work reliably.</string>
|
||||
|
||||
<string name="call_select_sound_device">Select Sound Device</string>
|
||||
<string name="sound_device_phone">Phone</string>
|
||||
<string name="sound_device_speaker">Speaker</string>
|
||||
|
|
Loading…
Reference in a new issue