Webrtc call: get back on green banner
This commit is contained in:
parent
74915c1e9e
commit
d973cd7848
|
@ -1,156 +0,0 @@
|
||||||
/*
|
|
||||||
* 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<CurrentCallsCardView>? = 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<WebRtcCall>) {
|
|
||||||
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<WebRtcCall>) {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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.content.res.ColorStateList
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
|
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
|
||||||
|
) : FrameLayout(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))
|
||||||
|
val outValue = TypedValue().also {
|
||||||
|
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, it, true)
|
||||||
|
}
|
||||||
|
foreground = AppCompatResources.getDrawable(context, outValue.resourceId)
|
||||||
|
setOnClickListener { callback?.onTapToReturnToCall() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun render(calls: List<WebRtcCall>, formattedDuration: String) {
|
||||||
|
val connectedCalls = calls.filter {
|
||||||
|
it.mxCall.state is CallState.Connected
|
||||||
|
}
|
||||||
|
val heldCalls = connectedCalls.filter {
|
||||||
|
it.isLocalOnHold || it.isRemoteOnHold
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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 androidx.core.view.isVisible
|
||||||
|
import im.vector.app.features.call.webrtc.WebRtcCall
|
||||||
|
import org.matrix.android.sdk.api.session.call.CallState
|
||||||
|
|
||||||
|
class CurrentCallsViewPresenter {
|
||||||
|
|
||||||
|
private var currentCallsView: CurrentCallsView? = null
|
||||||
|
private var currentCall: WebRtcCall? = null
|
||||||
|
private var calls: List<WebRtcCall> = emptyList()
|
||||||
|
|
||||||
|
private val tickListener = object : WebRtcCall.Listener {
|
||||||
|
override fun onTick(formattedDuration: String) {
|
||||||
|
currentCallsView?.render(calls, formattedDuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateCall(currentCall: WebRtcCall?, calls: List<WebRtcCall>) {
|
||||||
|
this.currentCall?.removeListener(tickListener)
|
||||||
|
this.currentCall = currentCall
|
||||||
|
this.currentCall?.addListener(tickListener)
|
||||||
|
this.calls = calls
|
||||||
|
val hasActiveCall = currentCall?.mxCall?.state is CallState.Connected
|
||||||
|
currentCallsView?.isVisible = hasActiveCall
|
||||||
|
if (hasActiveCall) {
|
||||||
|
currentCallsView?.render(calls, currentCall?.formattedDuration() ?: "")
|
||||||
|
} else {
|
||||||
|
currentCallsView?.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(activeCallView: CurrentCallsView, interactionListener: CurrentCallsView.Callback) {
|
||||||
|
this.currentCallsView = activeCallView
|
||||||
|
this.currentCallsView?.callback = interactionListener
|
||||||
|
this.currentCall?.addListener(tickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unBind() {
|
||||||
|
this.currentCallsView?.callback = null
|
||||||
|
this.currentCall?.removeListener(tickListener)
|
||||||
|
currentCallsView = null
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,8 @@ import im.vector.app.core.platform.ToolbarConfigurable
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.ui.views.CurrentCallsCardView
|
import im.vector.app.core.ui.views.CurrentCallsView
|
||||||
|
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
|
||||||
import im.vector.app.core.ui.views.KeysBackupBanner
|
import im.vector.app.core.ui.views.KeysBackupBanner
|
||||||
import im.vector.app.databinding.FragmentHomeDetailBinding
|
import im.vector.app.databinding.FragmentHomeDetailBinding
|
||||||
import im.vector.app.features.call.SharedKnownCallsViewModel
|
import im.vector.app.features.call.SharedKnownCallsViewModel
|
||||||
|
@ -56,7 +57,6 @@ import im.vector.app.features.themes.ThemeUtils
|
||||||
import im.vector.app.features.workers.signout.BannerState
|
import im.vector.app.features.workers.signout.BannerState
|
||||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
||||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewState
|
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.group.model.GroupSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||||
|
@ -69,12 +69,11 @@ class HomeDetailFragment @Inject constructor(
|
||||||
private val colorProvider: ColorProvider,
|
private val colorProvider: ColorProvider,
|
||||||
private val alertManager: PopupAlertManager,
|
private val alertManager: PopupAlertManager,
|
||||||
private val callManager: WebRtcCallManager,
|
private val callManager: WebRtcCallManager,
|
||||||
private val vectorPreferences: VectorPreferences,
|
private val vectorPreferences: VectorPreferences
|
||||||
private val session: Session
|
|
||||||
) : VectorBaseFragment<FragmentHomeDetailBinding>(),
|
) : VectorBaseFragment<FragmentHomeDetailBinding>(),
|
||||||
KeysBackupBanner.Delegate,
|
KeysBackupBanner.Delegate,
|
||||||
ServerBackupStatusViewModel.Factory,
|
CurrentCallsView.Callback,
|
||||||
CurrentCallsCardView.Callback {
|
ServerBackupStatusViewModel.Factory {
|
||||||
|
|
||||||
private val viewModel: HomeDetailViewModel by fragmentViewModel()
|
private val viewModel: HomeDetailViewModel by fragmentViewModel()
|
||||||
private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel()
|
private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel()
|
||||||
|
@ -117,6 +116,8 @@ class HomeDetailFragment @Inject constructor(
|
||||||
return FragmentHomeDetailBinding.inflate(inflater, container, false)
|
return FragmentHomeDetailBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val currentCallsViewPresenter = CurrentCallsViewPresenter()
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
|
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
|
||||||
|
@ -188,11 +189,16 @@ class HomeDetailFragment @Inject constructor(
|
||||||
sharedCallActionViewModel
|
sharedCallActionViewModel
|
||||||
.liveKnownCalls
|
.liveKnownCalls
|
||||||
.observe(viewLifecycleOwner, {
|
.observe(viewLifecycleOwner, {
|
||||||
views.currentCallsCardView.render(callManager.getCurrentCall(), callManager.getCalls())
|
currentCallsViewPresenter.updateCall(callManager.getCurrentCall(), callManager.getCalls())
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
currentCallsViewPresenter.unBind()
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
// update notification tab if needed
|
// update notification tab if needed
|
||||||
|
@ -289,11 +295,7 @@ class HomeDetailFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupActiveCallView() {
|
private fun setupActiveCallView() {
|
||||||
views.currentCallsCardView.apply {
|
currentCallsViewPresenter.bind(views.currentCallsView, this)
|
||||||
this.avatarRenderer = this@HomeDetailFragment.avatarRenderer
|
|
||||||
this.session = this@HomeDetailFragment.session
|
|
||||||
this.callback = this@HomeDetailFragment
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
|
|
|
@ -89,7 +89,9 @@ import im.vector.app.core.intent.getMimeTypeFromUri
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.core.platform.showOptimizedSnackbar
|
import im.vector.app.core.platform.showOptimizedSnackbar
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.ui.views.CurrentCallsCardView
|
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
|
||||||
|
|
||||||
|
import im.vector.app.core.ui.views.CurrentCallsView
|
||||||
import im.vector.app.core.ui.views.FailedMessagesWarningView
|
import im.vector.app.core.ui.views.FailedMessagesWarningView
|
||||||
import im.vector.app.core.ui.views.NotificationAreaView
|
import im.vector.app.core.ui.views.NotificationAreaView
|
||||||
import im.vector.app.core.utils.Debouncer
|
import im.vector.app.core.utils.Debouncer
|
||||||
|
@ -240,7 +242,7 @@ class RoomDetailFragment @Inject constructor(
|
||||||
AttachmentTypeSelectorView.Callback,
|
AttachmentTypeSelectorView.Callback,
|
||||||
AttachmentsHelper.Callback,
|
AttachmentsHelper.Callback,
|
||||||
GalleryOrCameraDialogHelper.Listener,
|
GalleryOrCameraDialogHelper.Listener,
|
||||||
CurrentCallsCardView.Callback {
|
CurrentCallsView.Callback {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
|
@ -299,6 +301,7 @@ class RoomDetailFragment @Inject constructor(
|
||||||
private lateinit var attachmentTypeSelector: AttachmentTypeSelectorView
|
private lateinit var attachmentTypeSelector: AttachmentTypeSelectorView
|
||||||
|
|
||||||
private var lockSendButton = false
|
private var lockSendButton = false
|
||||||
|
private val currentCallsViewPresenter = CurrentCallsViewPresenter()
|
||||||
|
|
||||||
private lateinit var emojiPopup: EmojiPopup
|
private lateinit var emojiPopup: EmojiPopup
|
||||||
|
|
||||||
|
@ -346,7 +349,7 @@ class RoomDetailFragment @Inject constructor(
|
||||||
knownCallsViewModel
|
knownCallsViewModel
|
||||||
.liveKnownCalls
|
.liveKnownCalls
|
||||||
.observe(viewLifecycleOwner, {
|
.observe(viewLifecycleOwner, {
|
||||||
views.currentCallsCardView.render(callManager.getCurrentCall(), it)
|
currentCallsViewPresenter.updateCall(callManager.getCurrentCall(), it)
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -685,6 +688,7 @@ class RoomDetailFragment @Inject constructor(
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
timelineEventController.callback = null
|
timelineEventController.callback = null
|
||||||
timelineEventController.removeModelBuildListener(modelBuildListener)
|
timelineEventController.removeModelBuildListener(modelBuildListener)
|
||||||
|
currentCallsViewPresenter.unBind()
|
||||||
modelBuildListener = null
|
modelBuildListener = null
|
||||||
autoCompleter.clear()
|
autoCompleter.clear()
|
||||||
debouncer.cancelAll()
|
debouncer.cancelAll()
|
||||||
|
@ -730,11 +734,7 @@ class RoomDetailFragment @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupActiveCallView() {
|
private fun setupActiveCallView() {
|
||||||
views.currentCallsCardView.apply {
|
currentCallsViewPresenter.bind(views.currentCallsView, this)
|
||||||
this.callback = this@RoomDetailFragment
|
|
||||||
this.avatarRenderer = this@RoomDetailFragment.avatarRenderer
|
|
||||||
this.session = this@RoomDetailFragment.session
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToEvent(action: RoomDetailViewEvents.NavigateToEvent) {
|
private fun navigateToEvent(action: RoomDetailViewEvents.NavigateToEvent) {
|
||||||
|
|
|
@ -11,6 +11,15 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<im.vector.app.core.ui.views.CurrentCallsView
|
||||||
|
android:id="@+id/currentCallsView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/homeKeysBackupBanner"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/groupToolbar"
|
android:id="@+id/groupToolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -135,21 +144,6 @@
|
||||||
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
|
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/homeKeysBackupBanner" />
|
app:layout_constraintTop_toBottomOf="@+id/homeKeysBackupBanner" />
|
||||||
|
|
||||||
<im.vector.app.core.ui.views.CurrentCallsCardView
|
|
||||||
android:id="@+id/currentCallsCardView"
|
|
||||||
android:layout_width="@dimen/call_pip_width"
|
|
||||||
android:layout_height="@dimen/call_pip_height"
|
|
||||||
app:cardElevation="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:foreground="?attr/selectableItemBackground"
|
|
||||||
app:cardCornerRadius="@dimen/call_pip_radius"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/bottomNavigationView"
|
android:id="@+id/bottomNavigationView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
|
@ -12,6 +12,14 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<im.vector.app.core.ui.views.CurrentCallsView
|
||||||
|
android:id="@+id/currentCallsView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/roomToolbar"
|
android:id="@+id/roomToolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -104,11 +112,12 @@
|
||||||
android:id="@+id/removeJitsiWidgetView"
|
android:id="@+id/removeJitsiWidgetView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:visibility="visible"
|
|
||||||
android:background="?android:colorBackground"
|
android:background="?android:colorBackground"
|
||||||
android:minHeight="54dp"
|
android:minHeight="54dp"
|
||||||
|
android:visibility="visible"
|
||||||
app:layout_constraintTop_toBottomOf="@id/syncStateView" />
|
app:layout_constraintTop_toBottomOf="@id/syncStateView" />
|
||||||
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/timelineRecyclerView"
|
android:id="@+id/timelineRecyclerView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -123,14 +132,14 @@
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/jumpToReadMarkerView"
|
android:id="@+id/jumpToReadMarkerView"
|
||||||
style="?vctr_jump_to_unread_style"
|
style="?vctr_jump_to_unread_style"
|
||||||
app:chipIcon="@drawable/ic_jump_to_unread"
|
|
||||||
app:closeIcon="@drawable/ic_close_24dp"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:text="@string/room_jump_to_first_unread"
|
android:text="@string/room_jump_to_first_unread"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
|
app:chipIcon="@drawable/ic_jump_to_unread"
|
||||||
|
app:closeIcon="@drawable/ic_close_24dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/removeJitsiWidgetView"
|
app:layout_constraintTop_toBottomOf="@id/removeJitsiWidgetView"
|
||||||
|
@ -186,21 +195,6 @@
|
||||||
app:barrierDirection="top"
|
app:barrierDirection="top"
|
||||||
app:constraint_referenced_ids="composerLayout,notificationAreaView, failedMessagesWarningView" />
|
app:constraint_referenced_ids="composerLayout,notificationAreaView, failedMessagesWarningView" />
|
||||||
|
|
||||||
<im.vector.app.core.ui.views.CurrentCallsCardView
|
|
||||||
android:id="@+id/currentCallsCardView"
|
|
||||||
android:layout_width="@dimen/call_pip_width"
|
|
||||||
android:layout_height="@dimen/call_pip_height"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
app:cardElevation="8dp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:foreground="?attr/selectableItemBackground"
|
|
||||||
app:cardCornerRadius="@dimen/call_pip_radius"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/failedMessagesWarningView"/>
|
|
||||||
|
|
||||||
|
|
||||||
<im.vector.app.core.platform.BadgeFloatingActionButton
|
<im.vector.app.core.platform.BadgeFloatingActionButton
|
||||||
android:id="@+id/jumpToBottomView"
|
android:id="@+id/jumpToBottomView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?colorPrimary"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
tools:parentTag="android.widget.FrameLayout">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/currentCallsInfo"
|
||||||
|
style="@style/Widget.Vector.TextView.Body"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingTop="12dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
|
android:text="@string/call_only_active"
|
||||||
|
android:textColor="?colorOnPrimary" />
|
||||||
|
|
||||||
|
</merge>
|
|
@ -1,93 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="@dimen/call_pip_width"
|
|
||||||
android:layout_height="@dimen/call_pip_height"
|
|
||||||
android:backgroundTint="@color/bg_call_screen_blur"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
app:cardCornerRadius="@dimen/call_pip_radius"
|
|
||||||
tools:parentTag="com.google.android.material.card.MaterialCardView">
|
|
||||||
|
|
||||||
<org.webrtc.SurfaceViewRenderer
|
|
||||||
android:id="@+id/activeCallPiP"
|
|
||||||
android:layout_width="@dimen/call_pip_width"
|
|
||||||
android:layout_height="@dimen/call_pip_height"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="invisible" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/avatarViews"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/activeCallOpponentAvatar"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/otherCallOpponentAvatar"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:src="@tools:sample/avatars" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/activeCallPausedIcon"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="16dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/ic_call_small_pause"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/activeCallOpponentAvatar"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/activeCallOpponentAvatar"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/activeCallOpponentAvatar"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/activeCallOpponentAvatar" />
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/otherCallOpponentAvatar"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/activeCallOpponentAvatar"
|
|
||||||
tools:src="@tools:sample/avatars" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/otherCallPausedIcon"
|
|
||||||
android:layout_width="8dp"
|
|
||||||
android:layout_height="8dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/ic_call_small_pause"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/otherCallOpponentAvatar"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/otherCallOpponentAvatar"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/otherCallOpponentAvatar"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/otherCallOpponentAvatar" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/activeCallProgress"
|
|
||||||
style="?android:attr/progressBarStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:indeterminate="true"
|
|
||||||
android:indeterminateTint="@color/element_background_light"
|
|
||||||
android:indeterminateTintMode="src_atop"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
|
|
||||||
</merge>
|
|
Loading…
Reference in New Issue