Split ActiveCallOrConferenceFragment into two fragments
This commit is contained in:
parent
f86c9dc99c
commit
862c5e47c8
12 changed files with 599 additions and 224 deletions
|
@ -48,10 +48,7 @@ import org.linphone.activities.main.history.fragments.MasterCallLogsFragment
|
|||
import org.linphone.activities.main.settings.fragments.*
|
||||
import org.linphone.activities.main.sidemenu.fragments.SideMenuFragment
|
||||
import org.linphone.activities.voip.CallActivity
|
||||
import org.linphone.activities.voip.fragments.ActiveCallOrConferenceFragment
|
||||
import org.linphone.activities.voip.fragments.ConferenceParticipantsFragment
|
||||
import org.linphone.activities.voip.fragments.IncomingCallFragment
|
||||
import org.linphone.activities.voip.fragments.OutgoingCallFragment
|
||||
import org.linphone.activities.voip.fragments.*
|
||||
import org.linphone.contact.NativeContact
|
||||
import org.linphone.core.Address
|
||||
|
||||
|
@ -959,11 +956,21 @@ internal fun SideMenuFragment.navigateToScheduledConferences() {
|
|||
/* Calls related */
|
||||
|
||||
internal fun CallActivity.navigateToActiveCall() {
|
||||
if (findNavController(R.id.nav_host_fragment).currentDestination?.id != R.id.activeCallOrConferenceFragment) {
|
||||
if (findNavController(R.id.nav_host_fragment).currentDestination?.id != R.id.singleCallFragment) {
|
||||
findNavController(R.id.nav_host_fragment).navigate(
|
||||
R.id.action_global_activeCallOrConferenceFragment,
|
||||
R.id.action_global_singleCallFragment,
|
||||
null,
|
||||
popupTo(R.id.activeCallOrConferenceFragment, false)
|
||||
popupTo(R.id.conferenceCallFragment, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun CallActivity.navigateToConferenceCall() {
|
||||
if (findNavController(R.id.nav_host_fragment).currentDestination?.id != R.id.conferenceCallFragment) {
|
||||
findNavController(R.id.nav_host_fragment).navigate(
|
||||
R.id.action_global_conferenceCallFragment,
|
||||
null,
|
||||
popupTo(R.id.singleCallFragment, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -972,7 +979,7 @@ internal fun CallActivity.navigateToOutgoingCall() {
|
|||
findNavController(R.id.nav_host_fragment).navigate(
|
||||
R.id.action_global_outgoingCallFragment,
|
||||
null,
|
||||
popupTo(R.id.activeCallOrConferenceFragment, false)
|
||||
popupTo(R.id.singleCallFragment, false)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -982,60 +989,80 @@ internal fun CallActivity.navigateToIncomingCall(earlyMediaVideoEnabled: Boolean
|
|||
findNavController(R.id.nav_host_fragment).navigate(
|
||||
R.id.action_global_incomingCallFragment,
|
||||
args,
|
||||
popupTo(R.id.activeCallOrConferenceFragment, false)
|
||||
popupTo(R.id.singleCallFragment, false)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun OutgoingCallFragment.navigateToActiveCall() {
|
||||
findNavController().navigate(
|
||||
R.id.action_global_activeCallOrConferenceFragment,
|
||||
R.id.action_global_singleCallFragment,
|
||||
null,
|
||||
popupTo(R.id.activeCallOrConferenceFragment, false)
|
||||
popupTo(R.id.singleCallFragment, false)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun IncomingCallFragment.navigateToActiveCall() {
|
||||
findNavController().navigate(
|
||||
R.id.action_global_activeCallOrConferenceFragment,
|
||||
R.id.action_global_singleCallFragment,
|
||||
null,
|
||||
popupTo(R.id.activeCallOrConferenceFragment, false)
|
||||
popupTo(R.id.singleCallFragment, false)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ActiveCallOrConferenceFragment.navigateToCallsList() {
|
||||
if (findNavController().currentDestination?.id == R.id.activeCallOrConferenceFragment) {
|
||||
internal fun SingleCallFragment.navigateToCallsList() {
|
||||
if (findNavController().currentDestination?.id == R.id.singleCallFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_activeCallOrConferenceFragment_to_callsListFragment,
|
||||
R.id.action_singleCallFragment_to_callsListFragment,
|
||||
null,
|
||||
popupTo()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ActiveCallOrConferenceFragment.navigateToConferenceParticipants() {
|
||||
if (findNavController().currentDestination?.id == R.id.activeCallOrConferenceFragment) {
|
||||
internal fun SingleCallFragment.navigateToConferenceParticipants() {
|
||||
if (findNavController().currentDestination?.id == R.id.singleCallFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_activeCallOrConferenceFragment_to_conferenceParticipantsFragment,
|
||||
R.id.action_singleCallFragment_to_conferenceParticipantsFragment,
|
||||
null,
|
||||
popupTo()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ActiveCallOrConferenceFragment.navigateToChat(args: Bundle) {
|
||||
if (findNavController().currentDestination?.id == R.id.activeCallOrConferenceFragment) {
|
||||
internal fun SingleCallFragment.navigateToConferenceLayout() {
|
||||
if (findNavController().currentDestination?.id == R.id.singleCallFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_activeCallOrConferenceFragment_to_chatFragment,
|
||||
args,
|
||||
R.id.action_singleCallFragment_to_conferenceLayoutFragment,
|
||||
null,
|
||||
popupTo()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ActiveCallOrConferenceFragment.navigateToConferenceLayout() {
|
||||
if (findNavController().currentDestination?.id == R.id.activeCallOrConferenceFragment) {
|
||||
internal fun ConferenceCallFragment.navigateToCallsList() {
|
||||
if (findNavController().currentDestination?.id == R.id.conferenceCallFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_activeCallOrConferenceFragment_to_conferenceLayoutFragment,
|
||||
R.id.action_conferenceCallFragment_to_callsListFragment,
|
||||
null,
|
||||
popupTo()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ConferenceCallFragment.navigateToConferenceParticipants() {
|
||||
if (findNavController().currentDestination?.id == R.id.conferenceCallFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_conferenceCallFragment_to_conferenceParticipantsFragment,
|
||||
null,
|
||||
popupTo()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ConferenceCallFragment.navigateToConferenceLayout() {
|
||||
if (findNavController().currentDestination?.id == R.id.conferenceCallFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_conferenceCallFragment_to_conferenceLayoutFragment,
|
||||
null,
|
||||
popupTo()
|
||||
)
|
||||
|
|
|
@ -29,27 +29,28 @@ import androidx.databinding.DataBindingUtil
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import org.linphone.LinphoneApplication
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.ProximitySensorActivity
|
||||
import org.linphone.activities.*
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.navigateToActiveCall
|
||||
import org.linphone.activities.navigateToIncomingCall
|
||||
import org.linphone.activities.navigateToOutgoingCall
|
||||
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.compatibility.Compatibility
|
||||
import org.linphone.core.Call
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.VoipActivityBinding
|
||||
import org.linphone.mediastream.Version
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.PermissionHelper
|
||||
|
||||
class CallActivity : ProximitySensorActivity() {
|
||||
private lateinit var binding: VoipActivityBinding
|
||||
private lateinit var controlsViewModel: ControlsViewModel
|
||||
private lateinit var callsViewModel: CallsViewModel
|
||||
private lateinit var conferenceViewModel: ConferenceViewModel
|
||||
|
||||
private var foldingFeature: FoldingFeature? = null
|
||||
|
||||
|
@ -77,6 +78,8 @@ class CallActivity : ProximitySensorActivity() {
|
|||
|
||||
callsViewModel = ViewModelProvider(navControllerStoreOwner)[CallsViewModel::class.java]
|
||||
|
||||
conferenceViewModel = ViewModelProvider(navControllerStoreOwner)[ConferenceViewModel::class.java]
|
||||
|
||||
callsViewModel.noMoreCallEvent.observe(
|
||||
this
|
||||
) {
|
||||
|
@ -112,6 +115,39 @@ class CallActivity : ProximitySensorActivity() {
|
|||
Compatibility.enableAutoEnterPiP(this, enabled)
|
||||
}
|
||||
|
||||
callsViewModel.currentCallData.observe(
|
||||
this
|
||||
) { callData ->
|
||||
if (callData.call.conference == null) {
|
||||
Log.i("[Call] Current call isn't linked to a conference, changing fragment")
|
||||
navigateToActiveCall()
|
||||
} else {
|
||||
Log.i("[Call] Current call is linked to a conference, changing fragment")
|
||||
navigateToConferenceCall()
|
||||
}
|
||||
}
|
||||
|
||||
conferenceViewModel.conferenceExists.observe(
|
||||
this
|
||||
) { exists ->
|
||||
if (exists) {
|
||||
Log.i("[Call] Found active conference, changing fragment")
|
||||
navigateToConferenceCall()
|
||||
} else {
|
||||
Log.i("[Call] Conference no longer exists, changing fragment")
|
||||
navigateToActiveCall()
|
||||
}
|
||||
}
|
||||
|
||||
conferenceViewModel.isConferenceLocallyPaused.observe(
|
||||
this
|
||||
) { paused ->
|
||||
if (!paused) {
|
||||
Log.i("[Call] Entered conference, make sure conference fragment is active")
|
||||
navigateToConferenceCall()
|
||||
}
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
|
@ -151,28 +187,22 @@ class CallActivity : ProximitySensorActivity() {
|
|||
} else {
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
coreContext.removeCallOverlay()
|
||||
return
|
||||
}
|
||||
coreContext.removeCallOverlay()
|
||||
|
||||
val currentCall = coreContext.core.currentCall
|
||||
if (currentCall == null) {
|
||||
Log.e("[Call] No current call found, assume active call")
|
||||
navigateToActiveCall()
|
||||
return
|
||||
val currentCall = coreContext.core.currentCall
|
||||
when (currentCall?.state) {
|
||||
Call.State.OutgoingInit, Call.State.OutgoingEarlyMedia, Call.State.OutgoingProgress, Call.State.OutgoingRinging -> {
|
||||
navigateToOutgoingCall()
|
||||
}
|
||||
|
||||
when (currentCall.state) {
|
||||
Call.State.OutgoingInit, Call.State.OutgoingEarlyMedia, Call.State.OutgoingProgress, Call.State.OutgoingRinging -> {
|
||||
navigateToOutgoingCall()
|
||||
}
|
||||
Call.State.IncomingReceived, Call.State.IncomingEarlyMedia -> {
|
||||
val earlyMediaVideoEnabled = LinphoneApplication.corePreferences.acceptEarlyMedia &&
|
||||
currentCall.state == Call.State.IncomingEarlyMedia &&
|
||||
currentCall.currentParams.isVideoEnabled
|
||||
navigateToIncomingCall(earlyMediaVideoEnabled)
|
||||
}
|
||||
else -> navigateToActiveCall()
|
||||
Call.State.IncomingReceived, Call.State.IncomingEarlyMedia -> {
|
||||
val earlyMediaVideoEnabled = corePreferences.acceptEarlyMedia &&
|
||||
currentCall.state == Call.State.IncomingEarlyMedia &&
|
||||
currentCall.currentParams.isVideoEnabled
|
||||
navigateToIncomingCall(earlyMediaVideoEnabled)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,21 +281,7 @@ class CallActivity : ProximitySensorActivity() {
|
|||
}
|
||||
|
||||
private fun updateConstraintSetDependingOnFoldingState() {
|
||||
/*val feature = foldingFeature ?: return
|
||||
val constraintLayout = binding.constraintLayout
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
if (feature.state == FoldingFeature.State.HALF_OPENED && viewModel.videoEnabled.value == true) {
|
||||
set.setGuidelinePercent(R.id.hinge_top, 0.5f)
|
||||
set.setGuidelinePercent(R.id.hinge_bottom, 0.5f)
|
||||
viewModel.disable(true)
|
||||
} else {
|
||||
set.setGuidelinePercent(R.id.hinge_top, 0f)
|
||||
set.setGuidelinePercent(R.id.hinge_bottom, 1f)
|
||||
viewModel.disable(false)
|
||||
}
|
||||
|
||||
set.applyTo(constraintLayout)*/
|
||||
val feature = foldingFeature ?: return
|
||||
controlsViewModel.foldingStateChangedEvent.value = Event(feature.state)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.linphone.activities.voip.data
|
||||
|
||||
import android.view.View
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -47,7 +46,6 @@ open class CallData(val call: Call) : GenericContactData(call.remoteAddress) {
|
|||
|
||||
val isInRemoteConference = MutableLiveData<Boolean>()
|
||||
val remoteConferenceSubject = MutableLiveData<String>()
|
||||
val isActiveAndNotInConference = MediatorLiveData<Boolean>()
|
||||
|
||||
val isOutgoing = MutableLiveData<Boolean>()
|
||||
val isIncoming = MutableLiveData<Boolean>()
|
||||
|
@ -92,17 +90,6 @@ open class CallData(val call: Call) : GenericContactData(call.remoteAddress) {
|
|||
call.addListener(listener)
|
||||
isRemotelyRecorded.value = call.remoteParams?.isRecording
|
||||
|
||||
isActiveAndNotInConference.value = true
|
||||
isActiveAndNotInConference.addSource(isPaused) {
|
||||
updateActiveAndNotInConference()
|
||||
}
|
||||
isActiveAndNotInConference.addSource(isRemotelyPaused) {
|
||||
updateActiveAndNotInConference()
|
||||
}
|
||||
isActiveAndNotInConference.addSource(isInRemoteConference) {
|
||||
updateActiveAndNotInConference()
|
||||
}
|
||||
|
||||
update()
|
||||
// initChatRoom()
|
||||
|
||||
|
@ -308,7 +295,7 @@ open class CallData(val call: Call) : GenericContactData(call.remoteAddress) {
|
|||
Log.i("[Call] Starting 30 seconds timer to automatically decline video request")
|
||||
}
|
||||
|
||||
private fun updateActiveAndNotInConference() {
|
||||
isActiveAndNotInConference.value = isPaused.value == false && isRemotelyPaused.value == false && isInRemoteConference.value == false
|
||||
fun isActiveAndNotInConference(): Boolean {
|
||||
return isPaused.value == false && isRemotelyPaused.value == false && isInRemoteConference.value == false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||
* Copyright (c) 2010-2022 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
|
@ -31,36 +31,33 @@ import android.widget.RelativeLayout
|
|||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.*
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.navigateToCallsList
|
||||
import org.linphone.activities.navigateToConferenceLayout
|
||||
import org.linphone.activities.navigateToConferenceParticipants
|
||||
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.StatisticsListViewModel
|
||||
import org.linphone.activities.voip.views.RoundCornersTextureView
|
||||
import org.linphone.core.*
|
||||
import org.linphone.core.Conference
|
||||
import org.linphone.core.StreamType
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.VoipActiveCallOrConferenceFragmentBindingImpl
|
||||
import org.linphone.mediastream.video.capture.CaptureTextureView
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.databinding.VoipConferenceCallFragmentBinding
|
||||
|
||||
class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenceFragmentBindingImpl>() {
|
||||
class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding>() {
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val callsViewModel: CallsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val conferenceViewModel: ConferenceViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val statsViewModel: StatisticsListViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
||||
private var dialog: Dialog? = null
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.voip_active_call_or_conference_fragment
|
||||
override fun getLayoutId(): Int = R.layout.voip_conference_call_fragment
|
||||
|
||||
override fun onStart() {
|
||||
useMaterialSharedAxisXForwardAnimation = false
|
||||
|
@ -146,17 +143,6 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
}
|
||||
}
|
||||
|
||||
callsViewModel.currentCallData.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
if (it != null) {
|
||||
val timer = binding.root.findViewById<Chronometer>(R.id.active_call_timer)
|
||||
timer.base =
|
||||
SystemClock.elapsedRealtime() - (1000 * it.call.duration) // Linphone timestamps are in seconds
|
||||
timer.start()
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToConferenceParticipantsListEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
|
@ -181,7 +167,7 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToConferenceLayoutSettings.observe(
|
||||
controlsViewModel.goToConferenceLayoutSettingsEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume {
|
||||
|
@ -189,24 +175,18 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
}
|
||||
}
|
||||
|
||||
controlsViewModel.foldingStateChangedEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { state ->
|
||||
updateHingeRelatedConstraints(state)
|
||||
}
|
||||
}
|
||||
|
||||
callsViewModel.callUpdateEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { call ->
|
||||
if (call.state == Call.State.StreamsRunning) {
|
||||
dialog?.dismiss()
|
||||
} else if (call.state == Call.State.UpdatedByRemote) {
|
||||
if (coreContext.core.isVideoEnabled) {
|
||||
val remoteVideo = call.remoteParams?.isVideoEnabled ?: false
|
||||
val localVideo = call.currentParams.isVideoEnabled
|
||||
if (remoteVideo && !localVideo) {
|
||||
showCallVideoUpdateDialog(call)
|
||||
}
|
||||
} else {
|
||||
Log.w("[Call] Video display & capture are disabled, don't show video dialog")
|
||||
}
|
||||
}
|
||||
|
||||
val conference = call.conference
|
||||
if (conference != null && conferenceViewModel.conference.value == null) {
|
||||
Log.i("[Call] Found conference attached to call and no conference in dedicated view model, init & configure it")
|
||||
|
@ -216,7 +196,7 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToDialer.observe(
|
||||
controlsViewModel.goToDialerEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { isCallTransfer ->
|
||||
|
@ -229,12 +209,6 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
}
|
||||
}
|
||||
|
||||
val remoteLayout = binding.root.findViewById<LinearLayout>(R.id.remote_layout)
|
||||
val remoteVideoView = remoteLayout.findViewById<RoundCornersTextureView>(R.id.remote_video_surface)
|
||||
coreContext.core.nativeVideoWindowId = remoteVideoView
|
||||
val localVideoView = remoteLayout.findViewById<CaptureTextureView>(R.id.local_preview_video_surface)
|
||||
coreContext.core.nativePreviewWindowId = localVideoView
|
||||
|
||||
binding.stubbedConferenceActiveSpeakerLayout.setOnInflateListener { _, inflated ->
|
||||
Log.i("[Call] Active speaker conference layout inflated")
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
|
@ -271,16 +245,6 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedPausedCall.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedRemotelyPausedCall.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedPausedConference.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
|
@ -293,36 +257,6 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
controlsViewModel.hideExtraButtons(true)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
coreContext.core.nativeVideoWindowId = null
|
||||
coreContext.core.nativePreviewWindowId = null
|
||||
}
|
||||
|
||||
private fun showCallVideoUpdateDialog(call: Call) {
|
||||
val viewModel = DialogViewModel(AppUtils.getString(R.string.call_video_update_requested_dialog))
|
||||
dialog = DialogUtils.getVoipDialog(requireContext(), viewModel)
|
||||
|
||||
viewModel.showCancelButton(
|
||||
{
|
||||
coreContext.answerCallVideoUpdateRequest(call, false)
|
||||
dialog?.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_decline)
|
||||
)
|
||||
|
||||
viewModel.showOkButton(
|
||||
{
|
||||
coreContext.answerCallVideoUpdateRequest(call, true)
|
||||
dialog?.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_accept)
|
||||
)
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
private fun switchToFullScreenIfPossible(conference: Conference) {
|
||||
if (corePreferences.enableFullScreenWhenJoiningVideoConference) {
|
||||
if (conference.currentParams.isVideoEnabled) {
|
||||
|
@ -371,4 +305,20 @@ class ActiveCallOrConferenceFragment : GenericFragment<VoipActiveCallOrConferenc
|
|||
|
||||
timer.start()
|
||||
}
|
||||
|
||||
private fun updateHingeRelatedConstraints(state: FoldingFeature.State) {
|
||||
/*val constraintLayout = binding.constraintLayout
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
if (state == FoldingFeature.State.HALF_OPENED) {
|
||||
set.setGuidelinePercent(R.id.hinge_top, 0.5f)
|
||||
set.setGuidelinePercent(R.id.hinge_bottom, 0.5f)
|
||||
} else {
|
||||
set.setGuidelinePercent(R.id.hinge_top, 0f)
|
||||
set.setGuidelinePercent(R.id.hinge_bottom, 1f)
|
||||
}
|
||||
|
||||
set.applyTo(constraintLayout)*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2022 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.activities.voip.fragments
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.View
|
||||
import android.widget.Chronometer
|
||||
import android.widget.LinearLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.*
|
||||
import org.linphone.activities.main.MainActivity
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||
import org.linphone.activities.voip.viewmodels.StatisticsListViewModel
|
||||
import org.linphone.activities.voip.views.RoundCornersTextureView
|
||||
import org.linphone.core.*
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.VoipSingleCallFragmentBinding
|
||||
import org.linphone.mediastream.video.capture.CaptureTextureView
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
|
||||
class SingleCallFragment : GenericFragment<VoipSingleCallFragmentBinding>() {
|
||||
private val controlsViewModel: ControlsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val callsViewModel: CallsViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val conferenceViewModel: ConferenceViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
private val statsViewModel: StatisticsListViewModel by navGraphViewModels(R.id.call_nav_graph)
|
||||
|
||||
private var dialog: Dialog? = null
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.voip_single_call_fragment
|
||||
|
||||
override fun onStart() {
|
||||
useMaterialSharedAxisXForwardAnimation = false
|
||||
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
controlsViewModel.hideCallStats() // In case it was toggled on during incoming/outgoing fragment was visible
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
binding.controlsViewModel = controlsViewModel
|
||||
|
||||
binding.callsViewModel = callsViewModel
|
||||
|
||||
binding.conferenceViewModel = conferenceViewModel
|
||||
|
||||
binding.statsViewModel = statsViewModel
|
||||
|
||||
callsViewModel.currentCallData.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
if (it != null) {
|
||||
val timer = binding.root.findViewById<Chronometer>(R.id.active_call_timer)
|
||||
timer.base =
|
||||
SystemClock.elapsedRealtime() - (1000 * it.call.duration) // Linphone timestamps are in seconds
|
||||
timer.start()
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToConferenceParticipantsListEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume {
|
||||
navigateToConferenceParticipants()
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToChatEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume {
|
||||
goToChat()
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToCallsListEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume {
|
||||
navigateToCallsList()
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToConferenceLayoutSettingsEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume {
|
||||
navigateToConferenceLayout()
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.foldingStateChangedEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { state ->
|
||||
updateHingeRelatedConstraints(state)
|
||||
}
|
||||
}
|
||||
|
||||
callsViewModel.callUpdateEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { call ->
|
||||
if (call.state == Call.State.StreamsRunning) {
|
||||
dialog?.dismiss()
|
||||
} else if (call.state == Call.State.UpdatedByRemote) {
|
||||
if (coreContext.core.isVideoEnabled) {
|
||||
val remoteVideo = call.remoteParams?.isVideoEnabled ?: false
|
||||
val localVideo = call.currentParams.isVideoEnabled
|
||||
if (remoteVideo && !localVideo) {
|
||||
showCallVideoUpdateDialog(call)
|
||||
}
|
||||
} else {
|
||||
Log.w("[Call] Video display & capture are disabled, don't show video dialog")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
controlsViewModel.goToDialerEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { isCallTransfer ->
|
||||
val intent = Intent()
|
||||
intent.setClass(requireContext(), MainActivity::class.java)
|
||||
intent.putExtra("Dialer", true)
|
||||
intent.putExtra("Transfer", isCallTransfer)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
val remoteLayout = binding.root.findViewById<LinearLayout>(R.id.remote_layout)
|
||||
val remoteVideoView = remoteLayout.findViewById<RoundCornersTextureView>(R.id.remote_video_surface)
|
||||
coreContext.core.nativeVideoWindowId = remoteVideoView
|
||||
val localVideoView = remoteLayout.findViewById<CaptureTextureView>(R.id.local_preview_video_surface)
|
||||
coreContext.core.nativePreviewWindowId = localVideoView
|
||||
|
||||
binding.stubbedAudioRoutes.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedNumpad.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedCallStats.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedPausedCall.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
|
||||
binding.stubbedRemotelyPausedCall.setOnInflateListener { _, inflated ->
|
||||
val binding = DataBindingUtil.bind<ViewDataBinding>(inflated)
|
||||
binding?.lifecycleOwner = viewLifecycleOwner
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
|
||||
controlsViewModel.hideExtraButtons(true)
|
||||
}
|
||||
|
||||
private fun showCallVideoUpdateDialog(call: Call) {
|
||||
val viewModel = DialogViewModel(AppUtils.getString(R.string.call_video_update_requested_dialog))
|
||||
dialog = DialogUtils.getVoipDialog(requireContext(), viewModel)
|
||||
|
||||
viewModel.showCancelButton(
|
||||
{
|
||||
coreContext.answerCallVideoUpdateRequest(call, false)
|
||||
dialog?.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_decline)
|
||||
)
|
||||
|
||||
viewModel.showOkButton(
|
||||
{
|
||||
coreContext.answerCallVideoUpdateRequest(call, true)
|
||||
dialog?.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_accept)
|
||||
)
|
||||
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
private fun goToChat() {
|
||||
val intent = Intent()
|
||||
intent.setClass(requireContext(), MainActivity::class.java)
|
||||
intent.putExtra("Chat", true)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun updateHingeRelatedConstraints(state: FoldingFeature.State) {
|
||||
/*val constraintLayout = binding.constraintLayout
|
||||
val set = ConstraintSet()
|
||||
set.clone(constraintLayout)
|
||||
|
||||
if (state == FoldingFeature.State.HALF_OPENED) {
|
||||
set.setGuidelinePercent(R.id.hinge_top, 0.5f)
|
||||
set.setGuidelinePercent(R.id.hinge_bottom, 0.5f)
|
||||
} else {
|
||||
set.setGuidelinePercent(R.id.hinge_top, 0f)
|
||||
set.setGuidelinePercent(R.id.hinge_bottom, 1f)
|
||||
}
|
||||
|
||||
set.applyTo(constraintLayout)*/
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import android.view.animation.LinearInterpolator
|
|||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
|
@ -90,7 +91,7 @@ class ControlsViewModel : ViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val goToConferenceLayoutSettings: MutableLiveData<Event<Boolean>> by lazy {
|
||||
val goToConferenceLayoutSettingsEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
|
@ -98,10 +99,14 @@ class ControlsViewModel : ViewModel() {
|
|||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
val goToDialer: MutableLiveData<Event<Boolean>> by lazy {
|
||||
val goToDialerEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val foldingStateChangedEvent: MutableLiveData<Event<FoldingFeature.State>> by lazy {
|
||||
MutableLiveData<Event<FoldingFeature.State>>()
|
||||
}
|
||||
|
||||
private val nonEarpieceOutputAudioDevice = MutableLiveData<Boolean>()
|
||||
|
||||
private var previewX: Float = 0f
|
||||
|
@ -405,15 +410,15 @@ class ControlsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
fun goToConferenceLayout() {
|
||||
goToConferenceLayoutSettings.value = Event(true)
|
||||
goToConferenceLayoutSettingsEvent.value = Event(true)
|
||||
}
|
||||
|
||||
fun goToDialerForCallTransfer() {
|
||||
goToDialer.value = Event(true)
|
||||
goToDialerEvent.value = Event(true)
|
||||
}
|
||||
|
||||
fun goToDialerForNewCall() {
|
||||
goToDialer.value = Event(false)
|
||||
goToDialerEvent.value = Event(false)
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_fragment"
|
||||
app:navGraph="@navigation/call_nav_graph"
|
||||
tools:layout="@layout/voip_active_call_or_conference_fragment" />
|
||||
tools:layout="@layout/voip_single_call_fragment" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
android:id="@+id/stubbed_conference_active_speaker_layout"
|
||||
android:inflatedId="@+id/conference_active_speaker_layout"
|
||||
android:layout="@layout/voip_conference_active_speaker"
|
||||
android:visibility="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:conferenceViewModel="@{conferenceViewModel}"
|
||||
|
@ -52,8 +52,8 @@
|
|||
<ViewStub
|
||||
android:id="@+id/stubbed_conference_grid_layout"
|
||||
android:layout="@layout/voip_conference_grid"
|
||||
android:visibility="@{conferenceViewModel.conferenceMosaicDisplayMode && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceMosaicDisplayMode && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{conferenceViewModel.conferenceMosaicDisplayMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceMosaicDisplayMode ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:conferenceViewModel="@{conferenceViewModel}"
|
||||
|
@ -62,22 +62,13 @@
|
|||
<ViewStub
|
||||
android:id="@+id/stubbed_conference_audio_only_layout"
|
||||
android:layout="@layout/voip_conference_audio_only"
|
||||
android:visibility="@{conferenceViewModel.conferenceAudioOnlyDisplayMode && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceAudioOnlyDisplayMode && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{conferenceViewModel.conferenceAudioOnlyDisplayMode ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceAudioOnlyDisplayMode ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:conferenceViewModel="@{conferenceViewModel}"
|
||||
app:controlsViewModel="@{controlsViewModel}"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/remote_layout"
|
||||
layout="@layout/voip_call"
|
||||
android:visibility="@{conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.GONE : View.VISIBLE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:viewModel="@{callsViewModel.currentCallData}"
|
||||
app:controlsViewModel="@{controlsViewModel}"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ViewStub
|
||||
|
@ -113,8 +104,8 @@
|
|||
<ViewStub
|
||||
android:id="@+id/stubbed_paused_conference"
|
||||
android:layout="@layout/voip_conference_paused"
|
||||
android:visibility="@{conferenceViewModel.conferenceExists && conferenceViewModel.isConferenceLocallyPaused && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.conferenceExists && conferenceViewModel.isConferenceLocallyPaused && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{conferenceViewModel.isConferenceLocallyPaused ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{conferenceViewModel.isConferenceLocallyPaused ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
|
@ -122,29 +113,6 @@
|
|||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||
app:conferenceViewModel="@{conferenceViewModel}" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_remotely_paused_call"
|
||||
android:layout="@layout/voip_call_paused_by_remote"
|
||||
android:visibility="@{callsViewModel.currentCallData.isRemotelyPaused ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{callsViewModel.currentCallData.isRemotelyPaused ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_paused_call"
|
||||
android:layout="@layout/voip_call_paused"
|
||||
android:visibility="@{callsViewModel.currentCallData.isPaused && !conferenceViewModel.conferenceExists ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{callsViewModel.currentCallData.isPaused && !conferenceViewModel.conferenceExists ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||
app:data="@{callsViewModel.currentCallData}" />
|
||||
|
||||
<LinearLayout
|
||||
android:onClick="@{() -> controlsViewModel.hideExtraButtons(false)}"
|
||||
android:visibility="@{controlsViewModel.showExtras ? View.VISIBLE : View.GONE, default=gone}"
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<ImageView
|
||||
android:onClick="@{() -> data.switchCamera()}"
|
||||
android:visibility="@{data.videoEnabled && data.isSwitchCameraAvailable() ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{data.videoEnabled && data.isSwitchCameraAvailable() && data.isInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
|
||||
<ImageView
|
||||
android:onClick="@{() -> data.switchCamera()}"
|
||||
android:visibility="@{data.videoEnabled && data.isSwitchCameraAvailable() ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{data.videoEnabled && data.isSwitchCameraAvailable() && data.isInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp"
|
||||
|
|
149
app/src/main/res/layout/voip_single_call_fragment.xml
Normal file
149
app/src/main/res/layout/voip_single_call_fragment.xml
Normal file
|
@ -0,0 +1,149 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:bind="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<import type="com.google.android.flexbox.FlexDirection" />
|
||||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||
<variable
|
||||
name="callsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
||||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||
<variable
|
||||
name="statsViewModel"
|
||||
type="org.linphone.activities.voip.viewmodels.StatisticsListViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/voipBackgroundColor">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@{controlsViewModel.fullScreenMode ? @color/black_color : @color/transparent_color}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||
android:layout_margin="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/voip_remote_margin_full_screen : @dimen/voip_remote_margin, default=@dimen/voip_remote_margin}">
|
||||
|
||||
<include
|
||||
android:id="@+id/remote_layout"
|
||||
layout="@layout/voip_call"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:viewModel="@{callsViewModel.currentCallData}"
|
||||
app:controlsViewModel="@{controlsViewModel}"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_audio_routes"
|
||||
android:layout="@layout/voip_buttons_audio_routes"
|
||||
android:visibility="@{controlsViewModel.audioRoutesEnabled ? View.VISIBLE : View.GONE}"
|
||||
app:inflatedVisibility="@{controlsViewModel.audioRoutesEnabled ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="12dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||
app:controlsViewModel="@{controlsViewModel}"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/primary_buttons"
|
||||
android:visibility="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? View.GONE : View.VISIBLE}"
|
||||
layout="@layout/voip_buttons"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/voip_buttons_fragment_size"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintWidth_max="@dimen/voip_buttons_max_width"
|
||||
app:controlsViewModel="@{controlsViewModel}"
|
||||
app:callsViewModel="@{callsViewModel}" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_remotely_paused_call"
|
||||
android:layout="@layout/voip_call_paused_by_remote"
|
||||
android:visibility="@{callsViewModel.currentCallData.isRemotelyPaused ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{callsViewModel.currentCallData.isRemotelyPaused ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_paused_call"
|
||||
android:layout="@layout/voip_call_paused"
|
||||
android:visibility="@{callsViewModel.currentCallData.isPaused ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{callsViewModel.currentCallData.isPaused ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||
app:data="@{callsViewModel.currentCallData}" />
|
||||
|
||||
<LinearLayout
|
||||
android:onClick="@{() -> controlsViewModel.hideExtraButtons(false)}"
|
||||
android:visibility="@{controlsViewModel.showExtras ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/voip_translucent_popup_background" />
|
||||
|
||||
<include
|
||||
layout="@layout/voip_buttons_extra"
|
||||
android:translationY="@{controlsViewModel.extraButtonsMenuTranslateY, default=@dimen/voip_call_extra_buttons_translate_y}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/voip_call_extra_buttons_height"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintWidth_max="@dimen/voip_extra_menu_max_width"
|
||||
app:controlsViewModel="@{controlsViewModel}"
|
||||
app:callsViewModel="@{callsViewModel}"
|
||||
app:conferenceViewModel="@{conferenceViewModel}"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_call_stats"
|
||||
android:layout="@layout/voip_call_stats"
|
||||
android:visibility="@{controlsViewModel.callStatsVisible ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{controlsViewModel.callStatsVisible ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:statsViewModel="@{statsViewModel}"
|
||||
app:controlsViewModel="@{controlsViewModel}"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/stubbed_numpad"
|
||||
android:layout="@layout/voip_numpad"
|
||||
android:visibility="@{controlsViewModel.numpadVisible ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:inflatedVisibility="@{controlsViewModel.numpadVisible ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:controlsViewModel="@{controlsViewModel}"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
|
@ -3,29 +3,52 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/call_nav_graph"
|
||||
app:startDestination="@id/activeCallOrConferenceFragment">
|
||||
app:startDestination="@id/singleCallFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/activeCallOrConferenceFragment"
|
||||
android:name="org.linphone.activities.voip.fragments.ActiveCallOrConferenceFragment"
|
||||
tools:layout="@layout/voip_active_call_or_conference_fragment"
|
||||
android:label="ActiveCallOrConferenceFragment" >
|
||||
android:id="@+id/singleCallFragment"
|
||||
android:name="org.linphone.activities.voip.fragments.SingleCallFragment"
|
||||
tools:layout="@layout/voip_single_call_fragment"
|
||||
android:label="SingleCallFragment" >
|
||||
<action
|
||||
android:id="@+id/action_activeCallOrConferenceFragment_to_callsListFragment"
|
||||
android:id="@+id/action_singleCallFragment_to_callsListFragment"
|
||||
app:destination="@id/callsListFragment" />
|
||||
<action
|
||||
android:id="@+id/action_activeCallOrConferenceFragment_to_conferenceParticipantsFragment"
|
||||
android:id="@+id/action_singleCallFragment_to_conferenceParticipantsFragment"
|
||||
app:destination="@id/conferenceParticipantsFragment" />
|
||||
<action
|
||||
android:id="@+id/action_activeCallOrConferenceFragment_to_chatFragment"
|
||||
android:id="@+id/action_singleCallFragment_to_chatFragment"
|
||||
app:destination="@id/chatFragment" />
|
||||
<action
|
||||
android:id="@+id/action_activeCallOrConferenceFragment_to_conferenceLayoutFragment"
|
||||
android:id="@+id/action_singleCallFragment_to_conferenceLayoutFragment"
|
||||
app:destination="@id/conferenceLayoutFragment" />
|
||||
</fragment>
|
||||
|
||||
<action android:id="@+id/action_global_activeCallOrConferenceFragment"
|
||||
app:destination="@id/activeCallOrConferenceFragment"/>
|
||||
<action android:id="@+id/action_global_singleCallFragment"
|
||||
app:destination="@id/singleCallFragment"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/conferenceCallFragment"
|
||||
android:name="org.linphone.activities.voip.fragments.ConferenceCallFragment"
|
||||
tools:layout="@layout/voip_conference_call_fragment"
|
||||
android:label="ConferenceCallFragment" >
|
||||
<action
|
||||
android:id="@+id/action_conferenceCallFragment_to_callsListFragment"
|
||||
app:destination="@id/callsListFragment" />
|
||||
<action
|
||||
android:id="@+id/action_conferenceCallFragment_to_conferenceParticipantsFragment"
|
||||
app:destination="@id/conferenceParticipantsFragment" />
|
||||
<action
|
||||
android:id="@+id/action_conferenceCallFragment_to_chatFragment"
|
||||
app:destination="@id/chatFragment" />
|
||||
<action
|
||||
android:id="@+id/action_conferenceCallFragment_to_conferenceLayoutFragment"
|
||||
app:destination="@id/conferenceLayoutFragment" />
|
||||
</fragment>
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_conferenceCallFragment"
|
||||
app:destination="@id/conferenceCallFragment"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/callsListFragment"
|
||||
|
|
Loading…
Reference in a new issue