diff --git a/build.gradle b/build.gradle
index b6c4a17559..48274d88bf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -44,6 +44,8 @@ allprojects {
includeGroupByRegex 'com\\.github\\.chrisbanes'
// PFLockScreen-Android
includeGroupByRegex 'com\\.github\\.vector-im'
+ // DraggableView
+ includeGroupByRegex 'com\\.github\\.hyuwah'
// Chat effects
includeGroupByRegex 'com\\.github\\.jetradarmobile'
diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml
index 88338f799b..e2e50449ce 100644
--- a/library/ui-styles/src/main/res/values/dimens.xml
+++ b/library/ui-styles/src/main/res/values/dimens.xml
@@ -28,6 +28,10 @@
20dp
4dp
+ 128dp
+ 88dp
+ 8dp
+
76dp
diff --git a/vector/build.gradle b/vector/build.gradle
index 7c01cb550e..36eee3329f 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -396,6 +396,7 @@ dependencies {
implementation "androidx.autofill:autofill:$autofill_version"
implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
+ implementation 'com.github.hyuwah:DraggableView:1.0.0'
// Custom Tab
implementation 'androidx.browser:browser:1.3.0'
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsCardView.kt b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsCardView.kt
new file mode 100644
index 0000000000..318664d720
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsCardView.kt
@@ -0,0 +1,156 @@
+/*
+ * 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.ui.views
+
+import android.content.Context
+import android.util.AttributeSet
+import androidx.core.content.ContextCompat
+import androidx.core.view.isVisible
+import com.google.android.material.card.MaterialCardView
+import im.vector.app.R
+import im.vector.app.databinding.ViewCurrentCallsCardBinding
+import im.vector.app.features.call.utils.EglUtils
+import im.vector.app.features.call.webrtc.WebRtcCall
+import im.vector.app.features.call.webrtc.getOpponentAsMatrixItem
+import im.vector.app.features.home.AvatarRenderer
+import io.github.hyuwah.draggableviewlib.DraggableView
+import io.github.hyuwah.draggableviewlib.setupDraggable
+import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.call.CallState
+import org.webrtc.RendererCommon
+
+class CurrentCallsCardView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : MaterialCardView(context, attrs, defStyleAttr) {
+
+ interface Callback {
+ fun onTapToReturnToCall()
+ }
+
+ private val views: ViewCurrentCallsCardBinding
+
+ private var activeCallPipInitialized = false
+ private var currentCall: WebRtcCall? = null
+ private var draggableView: DraggableView? = null
+
+ lateinit var avatarRenderer: AvatarRenderer
+ lateinit var session: Session
+ var callback: Callback? = null
+
+ init {
+ inflate(context, R.layout.view_current_calls_card, this)
+ isVisible = false
+ views = ViewCurrentCallsCardBinding.bind(this)
+ draggableView = setupDraggable().build()
+ setOnClickListener { callback?.onTapToReturnToCall() }
+ }
+
+ fun render(currentCall: WebRtcCall?, calls: List) {
+ views.activeCallPiP.let {
+ this.currentCall?.detachRenderers(listOf(it))
+ }
+ this.currentCall = currentCall
+ if (currentCall != null) {
+ isVisible = true
+ when (currentCall.mxCall.state) {
+ is CallState.LocalRinging, CallState.Idle -> {
+ isVisible = false
+ }
+ is CallState.Connected -> {
+ views.activeCallProgress.isVisible = false
+ val isVideoCall = currentCall.mxCall.isVideoCall
+ if (isVideoCall) {
+ renderVideoCall(currentCall)
+ } else {
+ renderVoiceCall(currentCall, calls)
+ }
+ }
+ else -> {
+ renderConnectingState(currentCall)
+ }
+ }
+ } else {
+ // NO ACTIVE CALL
+ isVisible = false
+ }
+ }
+
+ private fun renderConnectingState(currentCall: WebRtcCall) {
+ //TODO show dots
+ views.activeCallProgress.isVisible = true
+ views.activeCallPiP.isVisible = false
+ views.avatarViews.isVisible = false
+ currentCall.detachRenderers(listOf(views.activeCallPiP))
+ }
+
+ private fun renderVideoCall(currentCall: WebRtcCall) {
+ initIfNeeded()
+ views.activeCallPiP.isVisible = true
+ views.avatarViews.isVisible = false
+ currentCall.attachViewRenderers(null, views.activeCallPiP, null)
+ }
+
+ private fun renderVoiceCall(currentCall: WebRtcCall, calls: List) {
+ views.activeCallPiP.isVisible = false
+ views.avatarViews.isVisible = true
+ val isActiveCallPaused = currentCall.isLocalOnHold || currentCall.isRemoteOnHold
+ views.activeCallPausedIcon.isVisible = isActiveCallPaused
+ val activeOpponentMatrixItem = currentCall.getOpponentAsMatrixItem(session)
+ if (isActiveCallPaused) {
+ val colorFilter = ContextCompat.getColor(context, R.color.bg_call_screen_blur)
+ activeOpponentMatrixItem?.also {
+ avatarRenderer.renderBlur(it, views.activeCallOpponentAvatar, sampling = 2, rounded = true, colorFilter = colorFilter, addPlaceholder = true)
+ }
+ } else {
+ activeOpponentMatrixItem?.also {
+ avatarRenderer.render(it, views.activeCallOpponentAvatar)
+ }
+ }
+
+ val otherConnectedCall = calls.filter {
+ it.mxCall.state is CallState.Connected
+ }.firstOrNull {
+ it != currentCall
+ }
+ if (otherConnectedCall != null) {
+ views.otherCallOpponentAvatar.isVisible = true
+ views.otherCallPausedIcon.isVisible = true
+ otherConnectedCall.getOpponentAsMatrixItem(session)?.also { heldOpponentMatrixItem ->
+ avatarRenderer.render(heldOpponentMatrixItem, views.activeCallOpponentAvatar)
+ }
+ } else {
+ views.otherCallOpponentAvatar.isVisible = false
+ views.otherCallPausedIcon.isVisible = false
+ }
+ }
+
+ private fun initIfNeeded() {
+ if (!activeCallPipInitialized) {
+ EglUtils.rootEglBase?.let { eglBase ->
+ views.activeCallPiP.apply {
+ init(eglBase.eglBaseContext, null)
+ setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
+ setEnableHardwareScaler(true)
+ setZOrderMediaOverlay(true)
+ }
+ activeCallPipInitialized = true
+ }
+ }
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt b/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt
deleted file mode 100644
index d1332f18dc..0000000000
--- a/vector/src/main/java/im/vector/app/core/ui/views/CurrentCallsView.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2020 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.ui.views
-
-import android.content.Context
-import android.util.AttributeSet
-import android.widget.RelativeLayout
-import im.vector.app.R
-import im.vector.app.databinding.ViewCurrentCallsBinding
-import im.vector.app.features.call.webrtc.WebRtcCall
-import im.vector.app.features.themes.ThemeUtils
-import org.matrix.android.sdk.api.session.call.CallState
-
-class CurrentCallsView @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : RelativeLayout(context, attrs, defStyleAttr) {
-
- interface Callback {
- fun onTapToReturnToCall()
- }
-
- val views: ViewCurrentCallsBinding
- var callback: Callback? = null
-
- init {
- inflate(context, R.layout.view_current_calls, this)
- views = ViewCurrentCallsBinding.bind(this)
- setBackgroundColor(ThemeUtils.getColor(context, R.attr.colorPrimary))
- setOnClickListener { callback?.onTapToReturnToCall() }
- }
-
- fun render(calls: List, formattedDuration: String) {
- val connectedCalls = calls.filter {
- it.mxCall.state is CallState.Connected
- }
- val heldCalls = connectedCalls.filter {
- it.isLocalOnHold || it.remoteOnHold
- }
- if (connectedCalls.isEmpty()) return
- views.currentCallsInfo.text = if (connectedCalls.size == heldCalls.size) {
- resources.getQuantityString(R.plurals.call_only_paused, heldCalls.size, heldCalls.size)
- } else {
- if (heldCalls.isEmpty()) {
- resources.getString(R.string.call_only_active, formattedDuration)
- } else {
- resources.getQuantityString(R.plurals.call_one_active_and_other_paused, heldCalls.size, formattedDuration, heldCalls.size)
- }
- }
- }
-}
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/KnownCallsViewHolder.kt b/vector/src/main/java/im/vector/app/core/ui/views/KnownCallsViewHolder.kt
deleted file mode 100644
index d49cf929b6..0000000000
--- a/vector/src/main/java/im/vector/app/core/ui/views/KnownCallsViewHolder.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2020 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.ui.views
-
-import androidx.core.view.isVisible
-import com.google.android.material.card.MaterialCardView
-import im.vector.app.core.epoxy.onClick
-import im.vector.app.features.call.utils.EglUtils
-import im.vector.app.features.call.webrtc.WebRtcCall
-import org.matrix.android.sdk.api.session.call.CallState
-import org.webrtc.RendererCommon
-import org.webrtc.SurfaceViewRenderer
-
-class KnownCallsViewHolder {
-
- private var activeCallPiP: SurfaceViewRenderer? = null
- private var currentCallsView: CurrentCallsView? = null
- private var pipWrapper: MaterialCardView? = null
- private var currentCall: WebRtcCall? = null
- private var calls: List = emptyList()
-
- private var activeCallPipInitialized = false
-
- private val tickListener = object : WebRtcCall.Listener {
- override fun onTick(formattedDuration: String) {
- currentCallsView?.render(calls, formattedDuration)
- }
- }
-
- fun updateCall(currentCall: WebRtcCall?, calls: List) {
- activeCallPiP?.let {
- this.currentCall?.detachRenderers(listOf(it))
- }
- this.currentCall?.removeListener(tickListener)
- this.currentCall = currentCall
- this.currentCall?.addListener(tickListener)
- this.calls = calls
- val hasActiveCall = currentCall?.mxCall?.state is CallState.Connected
- if (hasActiveCall) {
- val isVideoCall = currentCall?.mxCall?.isVideoCall == true
- if (isVideoCall) initIfNeeded()
- currentCallsView?.isVisible = !isVideoCall
- currentCallsView?.render(calls, currentCall?.formattedDuration() ?: "")
- pipWrapper?.isVisible = isVideoCall
- activeCallPiP?.isVisible = isVideoCall
- activeCallPiP?.let {
- currentCall?.attachViewRenderers(null, it, null)
- }
- } else {
- currentCallsView?.isVisible = false
- activeCallPiP?.isVisible = false
- pipWrapper?.isVisible = false
- activeCallPiP?.let {
- currentCall?.detachRenderers(listOf(it))
- }
- }
- }
-
- private fun initIfNeeded() {
- if (!activeCallPipInitialized && activeCallPiP != null) {
- activeCallPiP?.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
- EglUtils.rootEglBase?.let { eglBase ->
- activeCallPiP?.init(eglBase.eglBaseContext, null)
- activeCallPiP?.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
- activeCallPiP?.setEnableHardwareScaler(true /* enabled */)
- activeCallPiP?.setZOrderMediaOverlay(true)
- activeCallPipInitialized = true
- }
- }
- }
-
- fun bind(activeCallPiP: SurfaceViewRenderer,
- activeCallView: CurrentCallsView,
- pipWrapper: MaterialCardView,
- interactionListener: CurrentCallsView.Callback) {
- this.activeCallPiP = activeCallPiP
- this.currentCallsView = activeCallView
- this.pipWrapper = pipWrapper
- this.currentCallsView?.callback = interactionListener
- pipWrapper.onClick {
- interactionListener.onTapToReturnToCall()
- }
- this.currentCall?.addListener(tickListener)
- }
-
- fun unBind() {
- activeCallPiP?.let {
- currentCall?.detachRenderers(listOf(it))
- }
- if (activeCallPipInitialized) {
- activeCallPiP?.release()
- }
- this.currentCallsView?.callback = null
- this.currentCall?.removeListener(tickListener)
- pipWrapper?.setOnClickListener(null)
- activeCallPiP = null
- currentCallsView = null
- pipWrapper = null
- }
-}
diff --git a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt
index a3e3a5d71d..c4b2c8370e 100644
--- a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt
@@ -73,7 +73,6 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment {
- views.ringingControls.isVisible = true
- views.ringingControlAccept.isVisible = false
- views.ringingControlDecline.isVisible = true
- views.connectedControls.isVisible = false
- }
is CallState.LocalRinging -> {
views.ringingControls.isVisible = true
views.ringingControlAccept.isVisible = true
views.ringingControlDecline.isVisible = true
views.connectedControls.isVisible = false
}
- is CallState.Connected -> {
- if (callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
- views.ringingControls.isVisible = false
- views.connectedControls.isVisible = true
- views.videoToggleIcon.isVisible = state.isVideoCall
- } else {
- views.ringingControls.isVisible = true
- views.ringingControlAccept.isVisible = false
- views.ringingControlDecline.isVisible = true
- views.connectedControls.isVisible = false
- }
+ is CallState.Connected,
+ is CallState.Dialing,
+ is CallState.Answering -> {
+ views.ringingControls.isVisible = false
+ views.connectedControls.isVisible = true
+ views.videoToggleIcon.isVisible = state.isVideoCall
+ views.moreIcon.isVisible = callState is CallState.Connected && callState.iceConnectionState == MxPeerConnectionState.CONNECTED
}
- is CallState.Terminated,
- null -> {
+ else -> {
views.ringingControls.isVisible = false
views.connectedControls.isVisible = false
}
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
index 602a68ea74..8bbc54f070 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -35,6 +35,7 @@ import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.viewModel
import com.airbnb.mvrx.withState
+import com.google.android.material.card.MaterialCardView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
@@ -53,6 +54,8 @@ import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.RoomDetailArgs
+import io.github.hyuwah.draggableviewlib.DraggableView
+import io.github.hyuwah.draggableviewlib.setupDraggable
import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.extensions.orFalse
@@ -96,6 +99,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
}
private var rootEglBase: EglBase? = null
+ private var pipDraggrableView: DraggableView? = null
var surfaceRenderersAreInitialized = false
@@ -188,19 +192,19 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
is CallState.Idle,
is CallState.CreateOffer,
is CallState.LocalRinging,
- is CallState.Dialing -> {
+ is CallState.Dialing -> {
views.callVideoGroup.isInvisible = true
views.callInfoGroup.isVisible = true
views.callToolbar.setSubtitle(R.string.call_ring)
configureCallInfo(state)
}
- is CallState.Answering -> {
+ is CallState.Answering -> {
views.callVideoGroup.isInvisible = true
views.callInfoGroup.isVisible = true
views.callToolbar.setSubtitle(R.string.call_connecting)
configureCallInfo(state)
}
- is CallState.Connected -> {
+ is CallState.Connected -> {
views.callToolbar.subtitle = state.formattedDuration
if (callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
if (state.isLocalOnHold || state.isRemoteOnHold) {
@@ -248,10 +252,10 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
views.callToolbar.setSubtitle(R.string.call_connecting)
}
}
- is CallState.Terminated -> {
+ is CallState.Terminated -> {
finish()
}
- null -> {
+ null -> {
}
}
}
@@ -290,7 +294,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
addPlaceholder = true
)
views.otherKnownCallLayout.isVisible = true
- views.otherSmallIsHeldIcon.isVisible = otherCall?.let { it.isLocalOnHold || it.remoteOnHold }.orFalse()
+ views.otherSmallIsHeldIcon.isVisible = otherCall?.let { it.isLocalOnHold || it.isRemoteOnHold }.orFalse()
}
}
@@ -303,6 +307,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
finish()
}
}
+ pipDraggrableView = views.pipRendererWrapper.setupDraggable().build()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
@@ -322,21 +327,21 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
}
// Init Picture in Picture renderer
- views.pipRenderer.init(rootEglBase!!.eglBaseContext, null)
- views.pipRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT)
-
+ views.pipRenderer.apply {
+ init(rootEglBase!!.eglBaseContext, null)
+ setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
+ setEnableHardwareScaler(true)
+ setZOrderMediaOverlay(true)
+ }
// Init Full Screen renderer
views.fullscreenRenderer.init(rootEglBase!!.eglBaseContext, null)
views.fullscreenRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
-
- views.pipRenderer.setZOrderMediaOverlay(true)
- views.pipRenderer.setEnableHardwareScaler(true /* enabled */)
views.fullscreenRenderer.setEnableHardwareScaler(true /* enabled */)
callManager.getCallById(callArgs.callId)?.attachViewRenderers(views.pipRenderer, views.fullscreenRenderer,
intent.getStringExtra(EXTRA_MODE)?.takeIf { isFirstCreation() })
- views.pipRenderer.setOnClickListener {
+ views.pipRendererWrapper.setOnClickListener {
callViewModel.handle(VectorCallViewActions.ToggleCamera)
}
surfaceRenderersAreInitialized = true
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
index e7b2b629e1..4c268ac8fb 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
@@ -60,7 +60,7 @@ class VectorCallViewModel @AssistedInject constructor(
setState {
copy(
isLocalOnHold = call?.isLocalOnHold ?: false,
- isRemoteOnHold = call?.remoteOnHold ?: false
+ isRemoteOnHold = call?.isRemoteOnHold ?: false
)
}
}
@@ -189,12 +189,14 @@ class VectorCallViewModel @AssistedInject constructor(
}
setState {
copy(
+ isAudioMuted = webRtcCall.micMuted,
+ isVideoEnabled = !webRtcCall.videoMuted,
isVideoCall = webRtcCall.mxCall.isVideoCall,
callState = Success(webRtcCall.mxCall.state),
callInfo = webRtcCall.extractCallInfo(),
device = currentSoundDevice ?: CallAudioManager.Device.PHONE,
isLocalOnHold = webRtcCall.isLocalOnHold,
- isRemoteOnHold = webRtcCall.remoteOnHold,
+ isRemoteOnHold = webRtcCall.isRemoteOnHold,
availableDevices = callManager.audioManager.availableDevices,
isFrontCamera = webRtcCall.currentCameraType() == CameraType.FRONT,
canSwitchCamera = webRtcCall.canSwitchCamera(),
diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
index d3a9dd7edf..6d838b2812 100644
--- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
+++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt
@@ -164,7 +164,7 @@ class WebRtcCall(
private set
var videoMuted = false
private set
- var remoteOnHold = false
+ var isRemoteOnHold = false
private set
var isLocalOnHold = false
private set
@@ -586,12 +586,12 @@ class WebRtcCall(
}
private fun updateMuteStatus() {
- val micShouldBeMuted = micMuted || remoteOnHold
+ val micShouldBeMuted = micMuted || isRemoteOnHold
localAudioTrack?.setEnabled(!micShouldBeMuted)
- remoteAudioTrack?.setEnabled(!remoteOnHold)
- val vidShouldBeMuted = videoMuted || remoteOnHold
+ remoteAudioTrack?.setEnabled(!isRemoteOnHold)
+ val vidShouldBeMuted = videoMuted || isRemoteOnHold
localVideoTrack?.setEnabled(!vidShouldBeMuted)
- remoteVideoTrack?.setEnabled(!remoteOnHold)
+ remoteVideoTrack?.setEnabled(!isRemoteOnHold)
}
/**
@@ -617,16 +617,16 @@ class WebRtcCall(
fun updateRemoteOnHold(onHold: Boolean) {
sessionScope?.launch(dispatcher) {
- if (remoteOnHold == onHold) return@launch
+ if (isRemoteOnHold == onHold) return@launch
val direction: RtpTransceiver.RtpTransceiverDirection
if (onHold) {
wasLocalOnHold = isLocalOnHold
- remoteOnHold = true
+ isRemoteOnHold = true
isLocalOnHold = true
direction = RtpTransceiver.RtpTransceiverDirection.SEND_ONLY
timer.pause()
} else {
- remoteOnHold = false
+ isRemoteOnHold = false
isLocalOnHold = wasLocalOnHold
onCallBecomeActive(this@WebRtcCall)
direction = RtpTransceiver.RtpTransceiverDirection.SEND_RECV
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
index dda3df3881..f06b39fff3 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
@@ -22,7 +22,6 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import androidx.core.view.get
import androidx.core.view.isVisible
import androidx.core.view.iterator
import androidx.fragment.app.Fragment
@@ -38,9 +37,8 @@ import im.vector.app.core.platform.ToolbarConfigurable
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.resources.ColorProvider
-import im.vector.app.core.ui.views.CurrentCallsView
+import im.vector.app.core.ui.views.CurrentCallsCardView
import im.vector.app.core.ui.views.KeysBackupBanner
-import im.vector.app.core.ui.views.KnownCallsViewHolder
import im.vector.app.databinding.FragmentHomeDetailBinding
import im.vector.app.features.call.SharedKnownCallsViewModel
import im.vector.app.features.call.VectorCallActivity
@@ -58,6 +56,7 @@ import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.workers.signout.BannerState
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
+import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.group.model.GroupSummary
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
@@ -70,11 +69,12 @@ class HomeDetailFragment @Inject constructor(
private val colorProvider: ColorProvider,
private val alertManager: PopupAlertManager,
private val callManager: WebRtcCallManager,
- private val vectorPreferences: VectorPreferences
+ private val vectorPreferences: VectorPreferences,
+ private val session: Session
) : VectorBaseFragment(),
KeysBackupBanner.Delegate,
- CurrentCallsView.Callback,
- ServerBackupStatusViewModel.Factory {
+ ServerBackupStatusViewModel.Factory,
+ CurrentCallsCardView.Callback {
private val viewModel: HomeDetailViewModel by fragmentViewModel()
private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel()
@@ -117,8 +117,6 @@ class HomeDetailFragment @Inject constructor(
return FragmentHomeDetailBinding.inflate(inflater, container, false)
}
- private val activeCallViewHolder = KnownCallsViewHolder()
-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
@@ -190,7 +188,7 @@ class HomeDetailFragment @Inject constructor(
sharedCallActionViewModel
.liveKnownCalls
.observe(viewLifecycleOwner, {
- activeCallViewHolder.updateCall(callManager.getCurrentCall(), callManager.getCalls())
+ views.currentCallsCardView.render(callManager.getCurrentCall(), callManager.getCalls())
invalidateOptionsMenu()
})
}
@@ -291,12 +289,11 @@ class HomeDetailFragment @Inject constructor(
}
private fun setupActiveCallView() {
- activeCallViewHolder.bind(
- views.activeCallPiP,
- views.activeCallView,
- views.activeCallPiPWrap,
- this
- )
+ views.currentCallsCardView.apply {
+ this.avatarRenderer = this@HomeDetailFragment.avatarRenderer
+ this.session = this@HomeDetailFragment.session
+ this.callback = this@HomeDetailFragment
+ }
}
private fun setupToolbar() {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index 3d99dc785f..636abab793 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -90,9 +90,8 @@ import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.showOptimizedSnackbar
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.ui.views.ActiveConferenceView
-import im.vector.app.core.ui.views.CurrentCallsView
+import im.vector.app.core.ui.views.CurrentCallsCardView
import im.vector.app.core.ui.views.FailedMessagesWarningView
-import im.vector.app.core.ui.views.KnownCallsViewHolder
import im.vector.app.core.ui.views.NotificationAreaView
import im.vector.app.core.utils.Debouncer
import im.vector.app.core.utils.DimensionConverter
@@ -239,7 +238,7 @@ class RoomDetailFragment @Inject constructor(
AttachmentTypeSelectorView.Callback,
AttachmentsHelper.Callback,
GalleryOrCameraDialogHelper.Listener,
- CurrentCallsView.Callback {
+ CurrentCallsCardView.Callback {
companion object {
/**
@@ -298,7 +297,6 @@ class RoomDetailFragment @Inject constructor(
private lateinit var attachmentTypeSelector: AttachmentTypeSelectorView
private var lockSendButton = false
- private val knownCallsViewHolder = KnownCallsViewHolder()
private lateinit var emojiPopup: EmojiPopup
@@ -344,7 +342,7 @@ class RoomDetailFragment @Inject constructor(
knownCallsViewModel
.liveKnownCalls
.observe(viewLifecycleOwner, {
- knownCallsViewHolder.updateCall(callManager.getCurrentCall(), it)
+ views.currentCallsCardView.render(callManager.getCurrentCall(), it)
invalidateOptionsMenu()
})
@@ -687,7 +685,6 @@ class RoomDetailFragment @Inject constructor(
override fun onDestroyView() {
timelineEventController.callback = null
timelineEventController.removeModelBuildListener(modelBuildListener)
- views.activeCallView.callback = null
modelBuildListener = null
autoCompleter.clear()
debouncer.cancelAll()
@@ -698,7 +695,6 @@ class RoomDetailFragment @Inject constructor(
}
override fun onDestroy() {
- knownCallsViewHolder.unBind()
roomDetailViewModel.handle(RoomDetailAction.ExitTrackingUnreadMessagesState)
super.onDestroy()
}
@@ -734,12 +730,11 @@ class RoomDetailFragment @Inject constructor(
}
private fun setupActiveCallView() {
- knownCallsViewHolder.bind(
- views.activeCallPiP,
- views.activeCallView,
- views.activeCallPiPWrap,
- this
- )
+ views.currentCallsCardView.apply {
+ this.callback = this@RoomDetailFragment
+ this.avatarRenderer = this@RoomDetailFragment.avatarRenderer
+ this.session = this@RoomDetailFragment.session
+ }
}
private fun navigateToEvent(action: RoomDetailViewEvents.NavigateToEvent) {
diff --git a/vector/src/main/res/drawable/ic_call_video_small.xml b/vector/src/main/res/drawable/ic_call_video_small.xml
index abb2d85719..5e2ae23598 100644
--- a/vector/src/main/res/drawable/ic_call_video_small.xml
+++ b/vector/src/main/res/drawable/ic_call_video_small.xml
@@ -9,4 +9,5 @@
+
diff --git a/vector/src/main/res/drawable/ic_call_videocam_off_active.xml b/vector/src/main/res/drawable/ic_call_videocam_off_active.xml
deleted file mode 100644
index 106317ed56..0000000000
--- a/vector/src/main/res/drawable/ic_call_videocam_off_active.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
diff --git a/vector/src/main/res/drawable/ic_call_videocam_off_default.xml b/vector/src/main/res/drawable/ic_call_videocam_off_default.xml
deleted file mode 100644
index 0b3d9baf04..0000000000
--- a/vector/src/main/res/drawable/ic_call_videocam_off_default.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
diff --git a/vector/src/main/res/drawable/ic_mic_off.xml b/vector/src/main/res/drawable/ic_mic_off.xml
new file mode 100644
index 0000000000..8e199f115a
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_mic_off.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/vector/src/main/res/drawable/ic_mic_on.xml b/vector/src/main/res/drawable/ic_mic_on.xml
new file mode 100644
index 0000000000..791b475704
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_mic_on.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/vector/src/main/res/drawable/ic_microphone_off.xml b/vector/src/main/res/drawable/ic_microphone_off.xml
deleted file mode 100644
index 92d5044902..0000000000
--- a/vector/src/main/res/drawable/ic_microphone_off.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
diff --git a/vector/src/main/res/drawable/ic_microphone_on.xml b/vector/src/main/res/drawable/ic_microphone_on.xml
deleted file mode 100644
index aaa9987860..0000000000
--- a/vector/src/main/res/drawable/ic_microphone_on.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
diff --git a/vector/src/main/res/drawable/ic_video.xml b/vector/src/main/res/drawable/ic_video.xml
index d751601281..e5f4eacedb 100644
--- a/vector/src/main/res/drawable/ic_video.xml
+++ b/vector/src/main/res/drawable/ic_video.xml
@@ -1,10 +1,11 @@
-
-
+
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_videocam.xml b/vector/src/main/res/drawable/ic_videocam.xml
deleted file mode 100644
index b7a50f9a57..0000000000
--- a/vector/src/main/res/drawable/ic_videocam.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/vector/src/main/res/layout/activity_call.xml b/vector/src/main/res/layout/activity_call.xml
index 94794799c4..0a6c89426f 100644
--- a/vector/src/main/res/layout/activity_call.xml
+++ b/vector/src/main/res/layout/activity_call.xml
@@ -29,15 +29,24 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
-
+ app:layout_constraintBottom_toTopOf="@id/callControlsView">
+
+
+
+
-
-
+ app:layout_constraintTop_toBottomOf="@+id/homeKeysBackupBanner" />
-
+ android:foreground="?attr/selectableItemBackground"
+ app:cardCornerRadius="@dimen/call_pip_radius"
+ app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
+ app:layout_constraintEnd_toEndOf="parent" />
-
-
-
-
-
-
+ app:layout_constraintBottom_toTopOf="@id/failedMessagesWarningView"/>
-
-
-
@@ -102,8 +102,8 @@
android:clickable="true"
android:contentDescription="@string/a11y_stop_camera"
android:focusable="true"
- android:padding="16dp"
- android:src="@drawable/ic_call_videocam_off_default"
+ android:padding="12dp"
+ android:src="@drawable/ic_video"
app:backgroundTint="?android:colorBackground"
app:tint="?vctr_content_primary"
tools:ignore="MissingConstraints,MissingPrefix" />
@@ -139,7 +139,7 @@
-
-
-
-
-
-
-
diff --git a/vector/src/main/res/layout/view_current_calls_card.xml b/vector/src/main/res/layout/view_current_calls_card.xml
new file mode 100644
index 0000000000..712de3280b
--- /dev/null
+++ b/vector/src/main/res/layout/view_current_calls_card.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+