Rework how audio only layout will be handled
This commit is contained in:
parent
7b933ad76b
commit
291ae367a6
19 changed files with 448 additions and 263 deletions
|
@ -23,6 +23,7 @@ import android.Manifest
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.activities.voip.ConferenceDisplayMode
|
||||||
import org.linphone.core.*
|
import org.linphone.core.*
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.utils.AudioRouteUtils
|
import org.linphone.utils.AudioRouteUtils
|
||||||
|
@ -44,9 +45,7 @@ class ConferenceWaitingRoomViewModel : ViewModel() {
|
||||||
|
|
||||||
val layoutMenuSelected = MutableLiveData<Boolean>()
|
val layoutMenuSelected = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val isActiveSpeakerLayoutSelected = MutableLiveData<Boolean>()
|
val selectedLayout = MutableLiveData<ConferenceDisplayMode>()
|
||||||
|
|
||||||
val isAudioOnlyLayoutSelected = MutableLiveData<Boolean>()
|
|
||||||
|
|
||||||
val isVideoAvailable = MutableLiveData<Boolean>()
|
val isVideoAvailable = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
@ -101,20 +100,17 @@ class ConferenceWaitingRoomViewModel : ViewModel() {
|
||||||
Log.i("[Conference Waiting Room] Microphone will be ${if (callParams.isMicEnabled) "enabled" else "muted"}")
|
Log.i("[Conference Waiting Room] Microphone will be ${if (callParams.isMicEnabled) "enabled" else "muted"}")
|
||||||
updateMicState()
|
updateMicState()
|
||||||
|
|
||||||
layoutMenuSelected.value = false
|
callParams.isVideoEnabled = isVideoAvailableInCore()
|
||||||
isActiveSpeakerLayoutSelected.value = false
|
|
||||||
isAudioOnlyLayoutSelected.value = false
|
|
||||||
updateLayout()
|
|
||||||
|
|
||||||
isVideoAvailable.value = isAudioOnlyLayoutSelected.value == false && (core.isVideoCaptureEnabled || core.isVideoPreviewEnabled)
|
|
||||||
callParams.isVideoEnabled = isVideoAvailable.value == true
|
|
||||||
callParams.videoDirection = if (core.videoActivationPolicy.automaticallyInitiate) MediaDirection.SendRecv else MediaDirection.RecvOnly
|
callParams.videoDirection = if (core.videoActivationPolicy.automaticallyInitiate) MediaDirection.SendRecv else MediaDirection.RecvOnly
|
||||||
Log.i("[Conference Waiting Room] Video will be ${if (callParams.isVideoEnabled) "enabled" else "disabled"}")
|
Log.i("[Conference Waiting Room] Video will be ${if (callParams.isVideoEnabled) "enabled" else "disabled"}")
|
||||||
updateVideoState()
|
updateVideoState()
|
||||||
|
|
||||||
|
layoutMenuSelected.value = false
|
||||||
|
updateLayout()
|
||||||
|
|
||||||
if (AudioRouteUtils.isBluetoothAudioRouteAvailable()) {
|
if (AudioRouteUtils.isBluetoothAudioRouteAvailable()) {
|
||||||
setBluetoothAudioRoute()
|
setBluetoothAudioRoute()
|
||||||
} else if (isVideoAvailable.value == true && isVideoEnabled.value == true) {
|
} else if (isVideoAvailableInCore() && isVideoEnabled.value == true) {
|
||||||
setSpeakerAudioRoute()
|
setSpeakerAudioRoute()
|
||||||
} else {
|
} else {
|
||||||
setEarpieceAudioRoute()
|
setEarpieceAudioRoute()
|
||||||
|
@ -209,22 +205,31 @@ class ConferenceWaitingRoomViewModel : ViewModel() {
|
||||||
|
|
||||||
fun setMosaicLayout() {
|
fun setMosaicLayout() {
|
||||||
Log.i("[Conference Waiting Room] Set default layout to Mosaic")
|
Log.i("[Conference Waiting Room] Set default layout to Mosaic")
|
||||||
coreContext.core.defaultConferenceLayout = ConferenceLayout.Grid
|
|
||||||
|
callParams.conferenceVideoLayout = ConferenceLayout.Grid
|
||||||
|
callParams.isVideoEnabled = isVideoAvailableInCore()
|
||||||
|
|
||||||
updateLayout()
|
updateLayout()
|
||||||
|
updateVideoState()
|
||||||
layoutMenuSelected.value = false
|
layoutMenuSelected.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setActiveSpeakerLayout() {
|
fun setActiveSpeakerLayout() {
|
||||||
Log.i("[Conference Waiting Room] Set default layout to ActiveSpeaker")
|
Log.i("[Conference Waiting Room] Set default layout to ActiveSpeaker")
|
||||||
coreContext.core.defaultConferenceLayout = ConferenceLayout.ActiveSpeaker
|
|
||||||
|
callParams.conferenceVideoLayout = ConferenceLayout.ActiveSpeaker
|
||||||
|
callParams.isVideoEnabled = isVideoAvailableInCore()
|
||||||
|
|
||||||
updateLayout()
|
updateLayout()
|
||||||
|
updateVideoState()
|
||||||
layoutMenuSelected.value = false
|
layoutMenuSelected.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setAudioOnlyLayout() {
|
fun setAudioOnlyLayout() {
|
||||||
Log.i("[Conference Waiting Room] Set default layout to AudioOnly")
|
Log.i("[Conference Waiting Room] Set default layout to AudioOnly, disabling video in call")
|
||||||
coreContext.core.defaultConferenceLayout = ConferenceLayout.Legacy // TODO: FIXME: Replace Legacy by AudioOnly
|
callParams.isVideoEnabled = false
|
||||||
updateLayout()
|
updateLayout()
|
||||||
|
updateVideoState()
|
||||||
layoutMenuSelected.value = false
|
layoutMenuSelected.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +238,7 @@ class ConferenceWaitingRoomViewModel : ViewModel() {
|
||||||
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
|
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
callParams.isVideoEnabled = isVideoAvailable.value == true
|
callParams.isVideoEnabled = isVideoAvailableInCore()
|
||||||
callParams.videoDirection = if (callParams.videoDirection == MediaDirection.SendRecv) MediaDirection.RecvOnly else MediaDirection.SendRecv
|
callParams.videoDirection = if (callParams.videoDirection == MediaDirection.SendRecv) MediaDirection.RecvOnly else MediaDirection.SendRecv
|
||||||
Log.i("[Conference Waiting Room] Video will be ${if (callParams.isVideoEnabled) "enabled" else "disabled"}")
|
Log.i("[Conference Waiting Room] Video will be ${if (callParams.isVideoEnabled) "enabled" else "disabled"}")
|
||||||
updateVideoState()
|
updateVideoState()
|
||||||
|
@ -241,7 +246,7 @@ class ConferenceWaitingRoomViewModel : ViewModel() {
|
||||||
|
|
||||||
fun enableVideo() {
|
fun enableVideo() {
|
||||||
Log.i("[Conference Waiting Room] Video will be enabled")
|
Log.i("[Conference Waiting Room] Video will be enabled")
|
||||||
callParams.isVideoEnabled = isVideoAvailable.value == true
|
callParams.isVideoEnabled = isVideoAvailableInCore()
|
||||||
callParams.videoDirection = MediaDirection.SendRecv
|
callParams.videoDirection = MediaDirection.SendRecv
|
||||||
updateVideoState()
|
updateVideoState()
|
||||||
}
|
}
|
||||||
|
@ -290,20 +295,25 @@ class ConferenceWaitingRoomViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateLayout() {
|
private fun updateLayout() {
|
||||||
val core = coreContext.core
|
if (!callParams.isVideoEnabled) {
|
||||||
val layout = core.defaultConferenceLayout
|
selectedLayout.value = ConferenceDisplayMode.AUDIO_ONLY
|
||||||
isActiveSpeakerLayoutSelected.value = layout == ConferenceLayout.ActiveSpeaker
|
} else {
|
||||||
isAudioOnlyLayoutSelected.value = layout == ConferenceLayout.Legacy // TODO: FIXME: Replace Legacy by AudioOnly
|
selectedLayout.value = when (callParams.conferenceVideoLayout) {
|
||||||
|
ConferenceLayout.Grid -> ConferenceDisplayMode.GRID
|
||||||
isVideoAvailable.value = isAudioOnlyLayoutSelected.value == false && (core.isVideoCaptureEnabled || core.isVideoPreviewEnabled)
|
else -> ConferenceDisplayMode.ACTIVE_SPEAKER
|
||||||
callParams.isVideoEnabled = isVideoAvailable.value == true && isAudioOnlyLayoutSelected.value == false
|
}
|
||||||
if (isAudioOnlyLayoutSelected.value == true) callParams.videoDirection = MediaDirection.RecvOnly
|
}
|
||||||
updateVideoState()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateVideoState() {
|
private fun updateVideoState() {
|
||||||
|
isVideoAvailable.value = callParams.isVideoEnabled
|
||||||
isVideoEnabled.value = callParams.isVideoEnabled && callParams.videoDirection == MediaDirection.SendRecv
|
isVideoEnabled.value = callParams.isVideoEnabled && callParams.videoDirection == MediaDirection.SendRecv
|
||||||
isSwitchCameraAvailable.value = callParams.isVideoEnabled && coreContext.showSwitchCameraButton()
|
isSwitchCameraAvailable.value = callParams.isVideoEnabled && coreContext.showSwitchCameraButton()
|
||||||
coreContext.core.isVideoPreviewEnabled = callParams.isVideoEnabled
|
coreContext.core.isVideoPreviewEnabled = callParams.isVideoEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isVideoAvailableInCore(): Boolean {
|
||||||
|
val core = coreContext.core
|
||||||
|
return core.isVideoCaptureEnabled || core.isVideoPreviewEnabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,6 @@ class ConferencesSettingsViewModel : GenericSettingsViewModel() {
|
||||||
labels.add(prefs.getString(R.string.conference_display_mode_mosaic))
|
labels.add(prefs.getString(R.string.conference_display_mode_mosaic))
|
||||||
layoutValues.add(ConferenceLayout.Grid.toInt())
|
layoutValues.add(ConferenceLayout.Grid.toInt())
|
||||||
|
|
||||||
labels.add(prefs.getString(R.string.conference_display_mode_audio_only))
|
|
||||||
layoutValues.add(ConferenceLayout.Legacy.toInt()) // TODO: FIXME: Use AudioOnly
|
|
||||||
|
|
||||||
layoutLabels.value = labels
|
layoutLabels.value = labels
|
||||||
layoutIndex.value = layoutValues.indexOf(core.defaultConferenceLayout.toInt())
|
layoutIndex.value = layoutValues.indexOf(core.defaultConferenceLayout.toInt())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
enum class ConferenceDisplayMode {
|
||||||
|
GRID,
|
||||||
|
ACTIVE_SPEAKER,
|
||||||
|
AUDIO_ONLY
|
||||||
|
}
|
|
@ -113,7 +113,6 @@ open class CallData(val call: Call) : GenericContactData(call.remoteAddress) {
|
||||||
displayableAddress.value = clone.asStringUriOnly()
|
displayableAddress.value = clone.asStringUriOnly()
|
||||||
|
|
||||||
update()
|
update()
|
||||||
// initChatRoom()
|
|
||||||
|
|
||||||
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(call.remoteAddress)
|
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(call.remoteAddress)
|
||||||
if (conferenceInfo != null) {
|
if (conferenceInfo != null) {
|
||||||
|
@ -167,6 +166,10 @@ open class CallData(val call: Call) : GenericContactData(call.remoteAddress) {
|
||||||
contextMenuClickListener?.onShowContextMenu(anchor, this)
|
contextMenuClickListener?.onShowContextMenu(anchor, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isActiveAndNotInConference(): Boolean {
|
||||||
|
return isPaused.value == false && isRemotelyPaused.value == false && isInRemoteConference.value == false
|
||||||
|
}
|
||||||
|
|
||||||
private fun isCallPaused(): Boolean {
|
private fun isCallPaused(): Boolean {
|
||||||
return when (call.state) {
|
return when (call.state) {
|
||||||
Call.State.Paused, Call.State.Pausing -> true
|
Call.State.Paused, Call.State.Pausing -> true
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.linphone.activities.main.MainActivity
|
||||||
import org.linphone.activities.navigateToCallsList
|
import org.linphone.activities.navigateToCallsList
|
||||||
import org.linphone.activities.navigateToConferenceLayout
|
import org.linphone.activities.navigateToConferenceLayout
|
||||||
import org.linphone.activities.navigateToConferenceParticipants
|
import org.linphone.activities.navigateToConferenceParticipants
|
||||||
|
import org.linphone.activities.voip.ConferenceDisplayMode
|
||||||
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
import org.linphone.activities.voip.viewmodels.CallsViewModel
|
||||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||||
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
import org.linphone.activities.voip.viewmodels.ControlsViewModel
|
||||||
|
@ -79,20 +80,11 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
|
|
||||||
binding.statsViewModel = statsViewModel
|
binding.statsViewModel = statsViewModel
|
||||||
|
|
||||||
conferenceViewModel.conferenceMosaicDisplayMode.observe(
|
conferenceViewModel.conferenceDisplayMode.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) {
|
) { displayMode ->
|
||||||
if (it) {
|
|
||||||
startTimer(R.id.active_conference_timer)
|
startTimer(R.id.active_conference_timer)
|
||||||
}
|
if (displayMode == ConferenceDisplayMode.ACTIVE_SPEAKER) {
|
||||||
}
|
|
||||||
|
|
||||||
conferenceViewModel.conferenceActiveSpeakerDisplayMode.observe(
|
|
||||||
viewLifecycleOwner
|
|
||||||
) {
|
|
||||||
if (it) {
|
|
||||||
startTimer(R.id.active_conference_timer)
|
|
||||||
|
|
||||||
if (conferenceViewModel.conferenceExists.value == true) {
|
if (conferenceViewModel.conferenceExists.value == true) {
|
||||||
Log.i("[Conference Call] Local participant is in conference and current layout is active speaker, updating Core's native window id")
|
Log.i("[Conference Call] Local participant is in conference and current layout is active speaker, updating Core's native window id")
|
||||||
val layout =
|
val layout =
|
||||||
|
@ -107,14 +99,6 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conferenceViewModel.conferenceAudioOnlyDisplayMode.observe(
|
|
||||||
viewLifecycleOwner
|
|
||||||
) {
|
|
||||||
if (it) {
|
|
||||||
startTimer(R.id.active_conference_timer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conferenceViewModel.conferenceParticipantDevices.observe(
|
conferenceViewModel.conferenceParticipantDevices.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) {
|
) {
|
||||||
|
@ -138,6 +122,20 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conferenceViewModel.conferenceDisplayMode.observe(
|
||||||
|
viewLifecycleOwner
|
||||||
|
) { layout ->
|
||||||
|
when (layout) {
|
||||||
|
ConferenceDisplayMode.AUDIO_ONLY -> {
|
||||||
|
controlsViewModel.fullScreenMode.value = false
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val conference = conferenceViewModel.conference.value
|
||||||
|
if (conference != null) switchToFullScreenIfPossible(conference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
controlsViewModel.goToConferenceParticipantsListEvent.observe(
|
controlsViewModel.goToConferenceParticipantsListEvent.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import androidx.navigation.navGraphViewModels
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.activities.GenericFragment
|
import org.linphone.activities.GenericFragment
|
||||||
|
import org.linphone.activities.voip.ConferenceDisplayMode
|
||||||
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
import org.linphone.activities.voip.viewmodels.ConferenceViewModel
|
||||||
import org.linphone.databinding.VoipConferenceLayoutFragmentBinding
|
import org.linphone.databinding.VoipConferenceLayoutFragmentBinding
|
||||||
|
|
||||||
|
@ -53,6 +54,16 @@ class ConferenceLayoutFragment : GenericFragment<VoipConferenceLayoutFragmentBin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conferenceViewModel.conferenceDisplayMode.observe(
|
||||||
|
viewLifecycleOwner
|
||||||
|
) {
|
||||||
|
binding.localPreviewVideoSurface.visibility = if (it == ConferenceDisplayMode.AUDIO_ONLY) {
|
||||||
|
View.GONE
|
||||||
|
} else {
|
||||||
|
View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.setDismissDialogClickListener {
|
binding.setDismissDialogClickListener {
|
||||||
val dialog = binding.root.findViewById<LinearLayout>(R.id.too_many_participants_dialog)
|
val dialog = binding.root.findViewById<LinearLayout>(R.id.too_many_participants_dialog)
|
||||||
dialog?.visibility = View.GONE
|
dialog?.visibility = View.GONE
|
||||||
|
|
|
@ -73,6 +73,7 @@ class CallsViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLastCallEnded(core: Core) {
|
override fun onLastCallEnded(core: Core) {
|
||||||
|
Log.i("[Calls] Last call ended")
|
||||||
currentCallData.value?.destroy()
|
currentCallData.value?.destroy()
|
||||||
noMoreCallEvent.value = Event(true)
|
noMoreCallEvent.value = Event(true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModel
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
|
import org.linphone.activities.voip.ConferenceDisplayMode
|
||||||
import org.linphone.activities.voip.data.ConferenceParticipantData
|
import org.linphone.activities.voip.data.ConferenceParticipantData
|
||||||
import org.linphone.activities.voip.data.ConferenceParticipantDeviceData
|
import org.linphone.activities.voip.data.ConferenceParticipantDeviceData
|
||||||
import org.linphone.core.*
|
import org.linphone.core.*
|
||||||
|
@ -43,9 +44,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
val conferenceCreationPending = MutableLiveData<Boolean>()
|
val conferenceCreationPending = MutableLiveData<Boolean>()
|
||||||
val conferenceParticipants = MutableLiveData<List<ConferenceParticipantData>>()
|
val conferenceParticipants = MutableLiveData<List<ConferenceParticipantData>>()
|
||||||
val conferenceParticipantDevices = MutableLiveData<List<ConferenceParticipantDeviceData>>()
|
val conferenceParticipantDevices = MutableLiveData<List<ConferenceParticipantDeviceData>>()
|
||||||
val conferenceMosaicDisplayMode = MutableLiveData<Boolean>()
|
val conferenceDisplayMode = MutableLiveData<ConferenceDisplayMode>()
|
||||||
val conferenceActiveSpeakerDisplayMode = MutableLiveData<Boolean>()
|
|
||||||
val conferenceAudioOnlyDisplayMode = MutableLiveData<Boolean>()
|
|
||||||
|
|
||||||
val isRecording = MutableLiveData<Boolean>()
|
val isRecording = MutableLiveData<Boolean>()
|
||||||
val isRemotelyRecorded = MutableLiveData<Boolean>()
|
val isRemotelyRecorded = MutableLiveData<Boolean>()
|
||||||
|
@ -64,10 +63,9 @@ class ConferenceViewModel : ViewModel() {
|
||||||
updateParticipantsList(conference)
|
updateParticipantsList(conference)
|
||||||
|
|
||||||
val count = conferenceParticipants.value.orEmpty().size
|
val count = conferenceParticipants.value.orEmpty().size
|
||||||
if (count > maxParticipantsForMosaicLayout && conferenceMosaicDisplayMode.value == true) {
|
if (count > maxParticipantsForMosaicLayout && conferenceDisplayMode.value == ConferenceDisplayMode.GRID) {
|
||||||
Log.w("[Conference] More than $maxParticipantsForMosaicLayout participants ($count), forcing active speaker layout")
|
Log.w("[Conference] More than $maxParticipantsForMosaicLayout participants ($count), forcing active speaker layout")
|
||||||
conferenceMosaicDisplayMode.value = false
|
conferenceDisplayMode.value = ConferenceDisplayMode.ACTIVE_SPEAKER
|
||||||
conferenceActiveSpeakerDisplayMode.value = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,9 +179,6 @@ class ConferenceViewModel : ViewModel() {
|
||||||
|
|
||||||
conferenceParticipants.value = arrayListOf()
|
conferenceParticipants.value = arrayListOf()
|
||||||
conferenceParticipantDevices.value = arrayListOf()
|
conferenceParticipantDevices.value = arrayListOf()
|
||||||
conferenceMosaicDisplayMode.value = false
|
|
||||||
conferenceActiveSpeakerDisplayMode.value = false
|
|
||||||
conferenceAudioOnlyDisplayMode.value = false
|
|
||||||
|
|
||||||
subject.value = AppUtils.getString(R.string.conference_default_title)
|
subject.value = AppUtils.getString(R.string.conference_default_title)
|
||||||
|
|
||||||
|
@ -290,27 +285,57 @@ class ConferenceViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeLayout(layout: ConferenceLayout) {
|
fun changeLayout(layout: ConferenceDisplayMode) {
|
||||||
Log.i("[Conference] Trying to change conference layout to $layout")
|
Log.i("[Conference] Trying to change conference layout to $layout")
|
||||||
val conference = conference.value
|
val conference = conference.value
|
||||||
if (conference != null) {
|
if (conference != null) {
|
||||||
conference.layout = layout
|
val call = conference.call
|
||||||
updateConferenceLayout(conference)
|
if (call != null) {
|
||||||
|
val params = call.core.createCallParams(call)
|
||||||
|
if (params == null) {
|
||||||
|
Log.e("[Conference] Failed to create call params from conference call!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params.isVideoEnabled = layout != ConferenceDisplayMode.AUDIO_ONLY
|
||||||
|
params.conferenceVideoLayout = when (layout) {
|
||||||
|
ConferenceDisplayMode.GRID -> ConferenceLayout.Grid
|
||||||
|
else -> ConferenceLayout.ActiveSpeaker
|
||||||
|
}
|
||||||
|
call.update(params)
|
||||||
|
|
||||||
|
conferenceDisplayMode.value = layout
|
||||||
|
val list = sortDevicesDataList(conferenceParticipantDevices.value.orEmpty())
|
||||||
|
conferenceParticipantDevices.value = list
|
||||||
|
} else {
|
||||||
|
Log.e("[Conference] Failed to get call from conference!")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e("[Conference] Conference is null in ConferenceViewModel")
|
Log.e("[Conference] Conference is null in ConferenceViewModel")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateConferenceLayout(conference: Conference) {
|
private fun updateConferenceLayout(conference: Conference) {
|
||||||
val layout = conference.layout
|
val call = conference.call
|
||||||
conferenceMosaicDisplayMode.value = layout == ConferenceLayout.Grid
|
if (call == null) {
|
||||||
conferenceActiveSpeakerDisplayMode.value = layout == ConferenceLayout.ActiveSpeaker
|
Log.e("[Conference] Conference call is null!")
|
||||||
conferenceAudioOnlyDisplayMode.value = layout == ConferenceLayout.Legacy // TODO: FIXME: Use AudioOnly layout
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val params = call.params
|
||||||
|
conferenceDisplayMode.value = if (!params.isVideoEnabled) {
|
||||||
|
ConferenceDisplayMode.AUDIO_ONLY
|
||||||
|
} else {
|
||||||
|
when (params.conferenceVideoLayout) {
|
||||||
|
ConferenceLayout.Grid -> ConferenceDisplayMode.GRID
|
||||||
|
else -> ConferenceDisplayMode.ACTIVE_SPEAKER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val list = sortDevicesDataList(conferenceParticipantDevices.value.orEmpty())
|
val list = sortDevicesDataList(conferenceParticipantDevices.value.orEmpty())
|
||||||
conferenceParticipantDevices.value = list
|
conferenceParticipantDevices.value = list
|
||||||
|
|
||||||
Log.i("[Conference] Conference current layout is: $layout")
|
Log.i("[Conference] Conference current layout is: ${conferenceDisplayMode.value}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun terminateConference(conference: Conference) {
|
private fun terminateConference(conference: Conference) {
|
||||||
|
@ -422,7 +447,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
if (meDeviceData != null) {
|
if (meDeviceData != null) {
|
||||||
val index = sortedList.indexOf(meDeviceData)
|
val index = sortedList.indexOf(meDeviceData)
|
||||||
val expectedIndex = if (conferenceActiveSpeakerDisplayMode.value == true) {
|
val expectedIndex = if (conferenceDisplayMode.value == ConferenceDisplayMode.ACTIVE_SPEAKER) {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
sortedList.size - 1
|
sortedList.size - 1
|
||||||
|
|
|
@ -353,9 +353,6 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
core.isVibrationOnIncomingCallEnabled = true
|
core.isVibrationOnIncomingCallEnabled = true
|
||||||
core.config.setBool("app", "incoming_call_vibration", false)
|
core.config.setBool("app", "incoming_call_vibration", false)
|
||||||
}
|
}
|
||||||
if (core.defaultConferenceLayout == ConferenceLayout.Legacy) {
|
|
||||||
core.defaultConferenceLayout = ConferenceLayout.ActiveSpeaker
|
|
||||||
}
|
|
||||||
|
|
||||||
initUserCertificates()
|
initUserCertificates()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<corners android:radius="6.7dp" />
|
||||||
|
<solid android:color="?attr/voipParticipantBackgroundColor"/>
|
||||||
|
</shape>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<stroke android:width="2dp" android:color="?attr/colorPrimary"/>
|
||||||
|
<corners android:radius="6.7dp"/>
|
||||||
|
</shape>
|
|
@ -3,7 +3,11 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<import type="org.linphone.activities.voip.ConferenceDisplayMode" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="viewModel"
|
name="viewModel"
|
||||||
type="org.linphone.activities.main.conference.viewmodels.ConferenceWaitingRoomViewModel" />
|
type="org.linphone.activities.main.conference.viewmodels.ConferenceWaitingRoomViewModel" />
|
||||||
|
@ -21,20 +25,19 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_margin="20dp"
|
android:layout_margin="20dp"
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
android:text="@{viewModel.subject, default=`Conference subject`}" />
|
android:text="@{viewModel.subject, default=`Conference subject`}" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
style="@style/conference_waiting_room_no_video_font"
|
style="@style/conference_waiting_room_no_video_font"
|
||||||
android:visibility="@{viewModel.isVideoEnabled ? View.GONE : View.VISIBLE}"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:text="@string/conference_waiting_room_video_disabled"/>
|
android:text="@string/conference_waiting_room_video_disabled"
|
||||||
|
android:visibility="@{viewModel.isVideoEnabled ? View.GONE : View.VISIBLE}" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:visibility="@{viewModel.isVideoEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_above="@id/conference_controls"
|
android:layout_above="@id/conference_controls"
|
||||||
|
@ -42,7 +45,8 @@
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginBottom="20dp"
|
android:layout_marginBottom="20dp"
|
||||||
android:background="@drawable/shape_remote_video_background">
|
android:background="@drawable/shape_remote_video_background"
|
||||||
|
android:visibility="@{viewModel.isVideoEnabled ? View.VISIBLE : View.GONE, default=gone}">
|
||||||
|
|
||||||
<org.linphone.activities.voip.views.RoundCornersTextureView
|
<org.linphone.activities.voip.views.RoundCornersTextureView
|
||||||
android:id="@+id/local_preview_video_surface"
|
android:id="@+id/local_preview_video_surface"
|
||||||
|
@ -73,131 +77,131 @@
|
||||||
android:id="@+id/conference_controls"
|
android:id="@+id/conference_controls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_above="@id/buttons"
|
android:layout_above="@id/buttons"
|
||||||
android:layout_marginBottom="20dp">
|
android:layout_marginBottom="20dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:onClick="@{() -> viewModel.cancel()}"
|
style="@style/big_orange_button_font"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
|
||||||
android:paddingLeft="20dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingRight="20dp"
|
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="20dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:gravity="center"
|
|
||||||
android:background="@drawable/shape_rect_gray_button"
|
|
||||||
android:text="@string/conference_waiting_room_cancel_call"
|
|
||||||
style="@style/big_orange_button_font"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:onClick="@{() -> viewModel.start()}"
|
|
||||||
android:enabled="@{!viewModel.joinInProgress}"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_rect_gray_button"
|
||||||
|
android:gravity="center"
|
||||||
|
android:onClick="@{() -> viewModel.cancel()}"
|
||||||
android:paddingLeft="20dp"
|
android:paddingLeft="20dp"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingRight="20dp"
|
android:paddingRight="20dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
|
android:text="@string/conference_waiting_room_cancel_call" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/big_orange_button_bold_font"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:gravity="center"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/shape_rect_orange_button"
|
android:background="@drawable/shape_rect_orange_button"
|
||||||
android:text="@string/conference_waiting_room_start_call"
|
android:enabled="@{!viewModel.joinInProgress}"
|
||||||
style="@style/big_orange_button_bold_font"/>
|
android:gravity="center"
|
||||||
|
android:onClick="@{() -> viewModel.start()}"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:text="@string/conference_waiting_room_start_call" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:visibility="@{viewModel.audioRoutesSelected ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@id/buttons"
|
android:layout_above="@id/buttons"
|
||||||
android:background="@drawable/shape_audio_routes_background"
|
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:orientation="vertical">
|
android:background="@drawable/shape_audio_routes_background"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="@{viewModel.audioRoutesSelected ? View.VISIBLE : View.GONE, default=gone}">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:selected="@{viewModel.isBluetoothHeadsetSelected}"
|
|
||||||
android:onClick="@{() -> viewModel.setBluetoothAudioRoute()}"
|
|
||||||
android:contentDescription="@string/content_description_use_bluetooth_headset"
|
|
||||||
android:layout_width="@dimen/voip_call_button_size"
|
android:layout_width="@dimen/voip_call_button_size"
|
||||||
android:layout_height="@dimen/voip_call_button_size"
|
android:layout_height="@dimen/voip_call_button_size"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
|
android:contentDescription="@string/content_description_use_bluetooth_headset"
|
||||||
|
android:onClick="@{() -> viewModel.setBluetoothAudioRoute()}"
|
||||||
|
android:selected="@{viewModel.isBluetoothHeadsetSelected}"
|
||||||
android:src="@drawable/icon_bluetooth" />
|
android:src="@drawable/icon_bluetooth" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:selected="@{!viewModel.isSpeakerSelected && !viewModel.isBluetoothHeadsetSelected}"
|
|
||||||
android:onClick="@{() -> viewModel.setEarpieceAudioRoute()}"
|
|
||||||
android:contentDescription="@string/content_description_use_earpiece"
|
|
||||||
android:layout_width="@dimen/voip_call_button_size"
|
android:layout_width="@dimen/voip_call_button_size"
|
||||||
android:layout_height="@dimen/voip_call_button_size"
|
android:layout_height="@dimen/voip_call_button_size"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
|
android:contentDescription="@string/content_description_use_earpiece"
|
||||||
|
android:onClick="@{() -> viewModel.setEarpieceAudioRoute()}"
|
||||||
|
android:selected="@{!viewModel.isSpeakerSelected && !viewModel.isBluetoothHeadsetSelected}"
|
||||||
android:src="@drawable/icon_earpiece" />
|
android:src="@drawable/icon_earpiece" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:selected="@{viewModel.isSpeakerSelected}"
|
|
||||||
android:onClick="@{() -> viewModel.setSpeakerAudioRoute()}"
|
|
||||||
android:contentDescription="@string/content_description_use_speaker"
|
|
||||||
android:layout_width="@dimen/voip_call_button_size"
|
android:layout_width="@dimen/voip_call_button_size"
|
||||||
android:layout_height="@dimen/voip_call_button_size"
|
android:layout_height="@dimen/voip_call_button_size"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
|
android:contentDescription="@string/content_description_use_speaker"
|
||||||
|
android:onClick="@{() -> viewModel.setSpeakerAudioRoute()}"
|
||||||
|
android:selected="@{viewModel.isSpeakerSelected}"
|
||||||
android:src="@drawable/icon_speaker" />
|
android:src="@drawable/icon_speaker" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:visibility="@{viewModel.layoutMenuSelected ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@id/buttons"
|
android:layout_above="@id/buttons"
|
||||||
android:background="@drawable/shape_audio_routes_background"
|
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:layout_marginEnd="15dp"
|
android:layout_marginEnd="15dp"
|
||||||
android:orientation="vertical">
|
android:layout_marginBottom="10dp"
|
||||||
|
android:background="@drawable/shape_audio_routes_background"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="@{viewModel.layoutMenuSelected ? View.VISIBLE : View.GONE, default=gone}">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:selected="@{!viewModel.isActiveSpeakerLayoutSelected && !viewModel.isAudioOnlyLayoutSelected}"
|
|
||||||
android:onClick="@{() -> viewModel.setMosaicLayout()}"
|
|
||||||
android:contentDescription="@string/conference_display_mode_mosaic"
|
|
||||||
android:layout_width="@dimen/voip_call_button_size"
|
android:layout_width="@dimen/voip_call_button_size"
|
||||||
android:layout_height="@dimen/voip_call_button_size"
|
android:layout_height="@dimen/voip_call_button_size"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
|
android:contentDescription="@string/conference_display_mode_mosaic"
|
||||||
|
android:onClick="@{() -> viewModel.setMosaicLayout()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
|
android:selected="@{viewModel.selectedLayout == ConferenceDisplayMode.GRID}"
|
||||||
android:src="@drawable/icon_conference_layout_grid"
|
android:src="@drawable/icon_conference_layout_grid"
|
||||||
app:tint="@color/white_color" />
|
app:tint="@color/white_color" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:selected="@{viewModel.isActiveSpeakerLayoutSelected}"
|
|
||||||
android:onClick="@{() -> viewModel.setActiveSpeakerLayout()}"
|
|
||||||
android:contentDescription="@string/conference_display_mode_active_speaker"
|
|
||||||
android:layout_width="@dimen/voip_call_button_size"
|
android:layout_width="@dimen/voip_call_button_size"
|
||||||
android:layout_height="@dimen/voip_call_button_size"
|
android:layout_height="@dimen/voip_call_button_size"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
|
android:contentDescription="@string/conference_display_mode_active_speaker"
|
||||||
|
android:onClick="@{() -> viewModel.setActiveSpeakerLayout()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
|
android:selected="@{viewModel.selectedLayout == ConferenceDisplayMode.ACTIVE_SPEAKER}"
|
||||||
android:src="@drawable/icon_conference_layout_active_speaker"
|
android:src="@drawable/icon_conference_layout_active_speaker"
|
||||||
app:tint="@color/white_color" />
|
app:tint="@color/white_color" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:selected="@{viewModel.isAudioOnlyLayoutSelected}"
|
|
||||||
android:onClick="@{() -> viewModel.setAudioOnlyLayout()}"
|
|
||||||
android:contentDescription="@string/conference_display_mode_audio_only"
|
|
||||||
android:layout_width="@dimen/voip_call_button_size"
|
android:layout_width="@dimen/voip_call_button_size"
|
||||||
android:layout_height="@dimen/voip_call_button_size"
|
android:layout_height="@dimen/voip_call_button_size"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
|
android:contentDescription="@string/conference_display_mode_audio_only"
|
||||||
|
android:onClick="@{() -> viewModel.setAudioOnlyLayout()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
|
android:selected="@{viewModel.selectedLayout == ConferenceDisplayMode.AUDIO_ONLY}"
|
||||||
android:src="@drawable/icon_conference_layout_audio_only"
|
android:src="@drawable/icon_conference_layout_audio_only"
|
||||||
app:tint="@color/white_color" />
|
app:tint="@color/white_color" />
|
||||||
|
|
||||||
|
@ -211,14 +215,14 @@
|
||||||
android:layout_marginBottom="10dp">
|
android:layout_marginBottom="10dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:contentDescription="@{viewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
|
||||||
android:onClick="@{() -> viewModel.toggleMuteMicrophone()}"
|
|
||||||
android:selected="@{viewModel.isMicrophoneMuted}"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
|
android:contentDescription="@{viewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
||||||
|
android:onClick="@{() -> viewModel.toggleMuteMicrophone()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
|
android:selected="@{viewModel.isMicrophoneMuted}"
|
||||||
android:src="@drawable/icon_toggle_mic"
|
android:src="@drawable/icon_toggle_mic"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintDimensionRatio="W,1:1"
|
app:layout_constraintDimensionRatio="W,1:1"
|
||||||
|
@ -245,45 +249,45 @@
|
||||||
android:visibility="@{viewModel.audioRoutesEnabled ? View.GONE : View.VISIBLE}" />
|
android:visibility="@{viewModel.audioRoutesEnabled ? View.GONE : View.VISIBLE}" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:onClick="@{() -> viewModel.toggleAudioRoutesMenu()}"
|
|
||||||
android:selected="@{viewModel.audioRoutesSelected}"
|
|
||||||
android:visibility="@{viewModel.audioRoutesEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
android:src="@drawable/icon_audio_routes"
|
android:contentDescription="@string/content_description_toggle_audio_menu"
|
||||||
|
android:onClick="@{() -> viewModel.toggleAudioRoutesMenu()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:contentDescription="@string/content_description_toggle_audio_menu"/>
|
android:selected="@{viewModel.audioRoutesSelected}"
|
||||||
|
android:src="@drawable/icon_audio_routes"
|
||||||
|
android:visibility="@{viewModel.audioRoutesEnabled ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:contentDescription="@{viewModel.isVideoEnabled ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
|
||||||
android:enabled="@{viewModel.isVideoAvailable}"
|
|
||||||
android:onClick="@{() -> viewModel.toggleVideo()}"
|
|
||||||
android:selected="@{viewModel.isVideoEnabled}"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
|
android:contentDescription="@{viewModel.isVideoEnabled ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
||||||
|
android:enabled="@{viewModel.isVideoAvailable}"
|
||||||
|
android:onClick="@{() -> viewModel.toggleVideo()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
|
android:selected="@{viewModel.isVideoEnabled}"
|
||||||
android:src="@drawable/icon_toggle_camera"
|
android:src="@drawable/icon_toggle_camera"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintDimensionRatio="W,1:1"
|
app:layout_constraintDimensionRatio="W,1:1"
|
||||||
app:layout_constraintStart_toEndOf="@id/speaker" />
|
app:layout_constraintStart_toEndOf="@id/speaker" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:onClick="@{() -> viewModel.toggleLayoutMenu()}"
|
|
||||||
android:selected="@{viewModel.layoutMenuSelected}"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:background="@drawable/button_toggle_background_reverse"
|
android:layout_height="match_parent"
|
||||||
android:src="@{viewModel.isActiveSpeakerLayoutSelected ? @drawable/icon_conference_layout_active_speaker : viewModel.isAudioOnlyLayoutSelected ? @drawable/icon_conference_layout_audio_only : @drawable/icon_conference_layout_grid, default=@drawable/icon_conference_layout_grid}"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
|
android:background="@drawable/button_toggle_background_reverse"
|
||||||
android:contentDescription="@string/content_description_toggle_layout_menu"
|
android:contentDescription="@string/content_description_toggle_layout_menu"
|
||||||
app:layout_constraintDimensionRatio="W,1:1"
|
android:onClick="@{() -> viewModel.toggleLayoutMenu()}"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:selected="@{viewModel.layoutMenuSelected}"
|
||||||
|
android:src="@{viewModel.selectedLayout == ConferenceDisplayMode.ACTIVE_SPEAKER ? @drawable/icon_conference_layout_active_speaker : viewModel.selectedLayout == ConferenceDisplayMode.AUDIO_ONLY ? @drawable/icon_conference_layout_audio_only : @drawable/icon_conference_layout_grid, default=@drawable/icon_conference_layout_grid}"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintDimensionRatio="W,1:1"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -3,13 +3,22 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<import type="org.linphone.activities.voip.ConferenceDisplayMode" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="controlsViewModel"
|
name="controlsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="callsViewModel"
|
name="callsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="conferenceViewModel"
|
||||||
|
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
@ -86,7 +95,7 @@
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
android:contentDescription="@{controlsViewModel.isVideoEnabled && controlsViewModel.isVideoSendReceive ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
android:contentDescription="@{controlsViewModel.isVideoEnabled && controlsViewModel.isVideoSendReceive ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
||||||
android:enabled="@{controlsViewModel.isVideoAvailable && !controlsViewModel.isVideoUpdateInProgress}"
|
android:enabled="@{controlsViewModel.isVideoAvailable && !controlsViewModel.isVideoUpdateInProgress && conferenceViewModel.conferenceDisplayMode != ConferenceDisplayMode.AUDIO_ONLY}}"
|
||||||
android:onClick="@{() -> controlsViewModel.toggleVideo()}"
|
android:onClick="@{() -> controlsViewModel.toggleVideo()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{controlsViewModel.isVideoEnabled && controlsViewModel.isVideoSendReceive}"
|
android:selected="@{controlsViewModel.isVideoEnabled && controlsViewModel.isVideoSendReceive}"
|
||||||
|
|
|
@ -4,13 +4,19 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<import type="org.linphone.activities.voip.ConferenceDisplayMode" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="controlsViewModel"
|
name="controlsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="callsViewModel"
|
name="callsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="conferenceViewModel"
|
name="conferenceViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||||
|
@ -145,7 +151,7 @@
|
||||||
style="@style/call_options_font"
|
style="@style/call_options_font"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:drawableTop="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode ? @drawable/icon_conference_layout_active_speaker : conferenceViewModel.conferenceAudioOnlyDisplayMode ? @drawable/icon_conference_layout_audio_only : @drawable/icon_conference_layout_grid, default=@drawable/icon_conference_layout_grid}"
|
android:drawableTop="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.ACTIVE_SPEAKER ? @drawable/icon_conference_layout_active_speaker : conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.AUDIO_ONLY ? @drawable/icon_conference_layout_audio_only : @drawable/icon_conference_layout_grid, default=@drawable/icon_conference_layout_grid}"
|
||||||
android:enabled="@{conferenceViewModel.isVideoConference}"
|
android:enabled="@{conferenceViewModel.isVideoConference}"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:onClick="@{() -> controlsViewModel.goToConferenceLayout()}"
|
android:onClick="@{() -> controlsViewModel.goToConferenceLayout()}"
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
android:layout_margin="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/voip_remote_margin_full_screen : @dimen/voip_remote_margin, default=@dimen/voip_remote_margin}"
|
android:layout_margin="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/voip_remote_margin_full_screen : @dimen/voip_remote_margin, default=@dimen/voip_remote_margin}"
|
||||||
android:visibility="@{inflatedVisibility}">
|
android:visibility="@{inflatedVisibility}">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/header"
|
android:id="@+id/header"
|
||||||
layout="@layout/voip_conference_header"
|
layout="@layout/voip_conference_header"
|
||||||
|
@ -37,41 +43,23 @@
|
||||||
layout="@layout/voip_remote_recording"
|
layout="@layout/voip_remote_recording"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/header"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:visibility="@{conferenceViewModel.isRemotelyRecorded ? View.VISIBLE : View.GONE, default=gone}" />
|
android:visibility="@{conferenceViewModel.isRemotelyRecorded ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.core.widget.NestedScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_above="@id/miniatures"
|
android:layout_marginTop="10dp">
|
||||||
android:layout_below="@id/remote_recording"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:background="@drawable/shape_remote_background">
|
|
||||||
|
|
||||||
<include
|
<LinearLayout
|
||||||
layout="@layout/voip_contact_avatar"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
app:data="@{conferenceViewModel.speakingParticipant}"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHeight_max="200dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/call_remote_name_font"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:orientation="vertical"
|
||||||
android:layout_marginBottom="10dp"
|
app:entries="@{conferenceViewModel.conferenceParticipantDevices}"
|
||||||
android:text="@{conferenceViewModel.speakingParticipant.contact.fullName ?? conferenceViewModel.speakingParticipant.displayName}"
|
app:layout="@{@layout/voip_conference_participant_remote_audio_only}" />
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,25 @@
|
||||||
xmlns:bind="http://schemas.android.com/tools">
|
xmlns:bind="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<import type="org.linphone.activities.voip.ConferenceDisplayMode" />
|
||||||
|
|
||||||
<import type="com.google.android.flexbox.FlexDirection" />
|
<import type="com.google.android.flexbox.FlexDirection" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="controlsViewModel"
|
name="controlsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="callsViewModel"
|
name="callsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="conferenceViewModel"
|
name="conferenceViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
type="org.linphone.activities.voip.viewmodels.ConferenceViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="statsViewModel"
|
name="statsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.StatisticsListViewModel" />
|
type="org.linphone.activities.voip.viewmodels.StatisticsListViewModel" />
|
||||||
|
@ -33,123 +41,124 @@
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_conference_active_speaker_layout"
|
android:id="@+id/stubbed_conference_active_speaker_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
android:inflatedId="@+id/conference_active_speaker_layout"
|
android:inflatedId="@+id/conference_active_speaker_layout"
|
||||||
android:layout="@layout/voip_conference_active_speaker"
|
android:layout="@layout/voip_conference_active_speaker"
|
||||||
android:visibility="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode ? View.VISIBLE : View.GONE, default=gone}"
|
android:visibility="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.ACTIVE_SPEAKER && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
app:inflatedVisibility="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode ? View.VISIBLE : View.GONE}"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
app:conferenceViewModel="@{conferenceViewModel}"
|
app:conferenceViewModel="@{conferenceViewModel}"
|
||||||
app:controlsViewModel="@{controlsViewModel}"
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
android:layout_height="0dp"
|
app:inflatedVisibility="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.ACTIVE_SPEAKER && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_conference_grid_layout"
|
android:id="@+id/stubbed_conference_grid_layout"
|
||||||
android:layout="@layout/voip_conference_grid"
|
|
||||||
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_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout="@layout/voip_conference_grid"
|
||||||
|
android:visibility="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.GRID && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
app:conferenceViewModel="@{conferenceViewModel}"
|
app:conferenceViewModel="@{conferenceViewModel}"
|
||||||
app:controlsViewModel="@{controlsViewModel}"
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
android:layout_height="0dp"
|
app:inflatedVisibility="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.GRID && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_conference_audio_only_layout"
|
android:id="@+id/stubbed_conference_audio_only_layout"
|
||||||
android:layout="@layout/voip_conference_audio_only"
|
|
||||||
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_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout="@layout/voip_conference_audio_only"
|
||||||
|
android:visibility="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.AUDIO_ONLY && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
app:conferenceViewModel="@{conferenceViewModel}"
|
app:conferenceViewModel="@{conferenceViewModel}"
|
||||||
app:controlsViewModel="@{controlsViewModel}"
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
android:layout_height="0dp"
|
app:inflatedVisibility="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.AUDIO_ONLY && conferenceViewModel.conferenceExists && !callsViewModel.currentCallData.isActiveAndNotInConference ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_audio_routes"
|
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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:layout_marginStart="12dp"
|
android:layout_marginStart="12dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:layout_marginBottom="10dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:layout="@layout/voip_buttons_audio_routes"
|
||||||
|
android:visibility="@{controlsViewModel.audioRoutesEnabled ? View.VISIBLE : View.GONE}"
|
||||||
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
|
app:inflatedVisibility="@{controlsViewModel.audioRoutesEnabled ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||||
app:controlsViewModel="@{controlsViewModel}"/>
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/primary_buttons"
|
android:id="@+id/primary_buttons"
|
||||||
android:visibility="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? View.GONE : View.VISIBLE}"
|
|
||||||
layout="@layout/voip_buttons"
|
layout="@layout/voip_buttons"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/voip_buttons_fragment_size"
|
android:layout_height="@dimen/voip_buttons_fragment_size"
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:layout_marginBottom="10dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:visibility="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? View.GONE : View.VISIBLE}"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:callsViewModel="@{callsViewModel}"
|
||||||
app:layout_constraintWidth_max="@dimen/voip_buttons_max_width"
|
app:conferenceViewModel="@{conferenceViewModel}"
|
||||||
app:controlsViewModel="@{controlsViewModel}"
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
app:callsViewModel="@{callsViewModel}" />
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintWidth_max="@dimen/voip_buttons_max_width" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_paused_conference"
|
android:id="@+id/stubbed_paused_conference"
|
||||||
android:layout="@layout/voip_conference_paused"
|
|
||||||
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_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
android:layout="@layout/voip_conference_paused"
|
||||||
|
android:visibility="@{conferenceViewModel.isConferenceLocallyPaused ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:conferenceViewModel="@{conferenceViewModel}"
|
||||||
|
app:inflatedVisibility="@{conferenceViewModel.isConferenceLocallyPaused ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
app:layout_constraintBottom_toTopOf="@id/primary_buttons"
|
||||||
app:conferenceViewModel="@{conferenceViewModel}" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:onClick="@{() -> controlsViewModel.hideExtraButtons(false)}"
|
|
||||||
android:visibility="@{controlsViewModel.showExtras ? View.VISIBLE : View.GONE, default=gone}"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/voip_translucent_popup_background" />
|
android:background="@color/voip_translucent_popup_background"
|
||||||
|
android:onClick="@{() -> controlsViewModel.hideExtraButtons(false)}"
|
||||||
|
android:visibility="@{controlsViewModel.showExtras ? View.VISIBLE : View.GONE, default=gone}" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/voip_buttons_extra"
|
layout="@layout/voip_buttons_extra"
|
||||||
android:translationY="@{controlsViewModel.extraButtonsMenuTranslateY, default=@dimen/voip_call_extra_buttons_translate_y}"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/voip_call_extra_buttons_height"
|
android:layout_height="@dimen/voip_call_extra_buttons_height"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="15dp"
|
android:layout_marginEnd="15dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:translationY="@{controlsViewModel.extraButtonsMenuTranslateY, default=@dimen/voip_call_extra_buttons_translate_y}"
|
||||||
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:callsViewModel="@{callsViewModel}"
|
||||||
app:conferenceViewModel="@{conferenceViewModel}"/>
|
app:conferenceViewModel="@{conferenceViewModel}"
|
||||||
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintWidth_max="@dimen/voip_extra_menu_max_width" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_call_stats"
|
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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:statsViewModel="@{statsViewModel}"
|
android:layout="@layout/voip_call_stats"
|
||||||
app:controlsViewModel="@{controlsViewModel}"/>
|
android:visibility="@{controlsViewModel.callStatsVisible ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
|
app:inflatedVisibility="@{controlsViewModel.callStatsVisible ? View.VISIBLE : View.GONE}"
|
||||||
|
app:statsViewModel="@{statsViewModel}" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/stubbed_numpad"
|
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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:controlsViewModel="@{controlsViewModel}"/>
|
android:layout="@layout/voip_numpad"
|
||||||
|
android:visibility="@{controlsViewModel.numpadVisible ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
|
app:inflatedVisibility="@{controlsViewModel.numpadVisible ? View.VISIBLE : View.GONE}" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
<import type="org.linphone.core.ConferenceLayout" />
|
<import type="org.linphone.activities.voip.ConferenceDisplayMode" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="cancelClickListener"
|
name="cancelClickListener"
|
||||||
|
@ -71,11 +71,11 @@
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:checked="@{conferenceViewModel.conferenceMosaicDisplayMode}"
|
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.GRID}"
|
||||||
android:drawableEnd="@drawable/icon_conference_layout_grid"
|
android:drawableEnd="@drawable/icon_conference_layout_grid"
|
||||||
android:drawableTint="?attr/voipDrawableColor"
|
android:drawableTint="?attr/voipDrawableColor"
|
||||||
android:enabled="@{conferenceViewModel.conferenceParticipantDevices.size() > conferenceViewModel.maxParticipantsForMosaicLayout ? false : true}"
|
android:enabled="@{conferenceViewModel.conferenceParticipantDevices.size() > conferenceViewModel.maxParticipantsForMosaicLayout ? false : true}"
|
||||||
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceLayout.Grid)}"
|
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.GRID)}"
|
||||||
android:text="@string/conference_display_mode_mosaic" />
|
android:text="@string/conference_display_mode_mosaic" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -90,11 +90,11 @@
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:checked="@{conferenceViewModel.conferenceActiveSpeakerDisplayMode}"
|
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.ACTIVE_SPEAKER}"
|
||||||
android:drawableEnd="@drawable/icon_conference_layout_active_speaker"
|
android:drawableEnd="@drawable/icon_conference_layout_active_speaker"
|
||||||
android:drawableTint="?attr/voipDrawableColor"
|
android:drawableTint="?attr/voipDrawableColor"
|
||||||
android:enabled="@{conferenceViewModel.conferenceParticipantDevices.size() > conferenceViewModel.maxParticipantsForMosaicLayout ? false : true}"
|
android:enabled="@{conferenceViewModel.conferenceParticipantDevices.size() > conferenceViewModel.maxParticipantsForMosaicLayout ? false : true}"
|
||||||
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceLayout.ActiveSpeaker)}"
|
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.ACTIVE_SPEAKER)}"
|
||||||
android:text="@string/conference_display_mode_active_speaker" />
|
android:text="@string/conference_display_mode_active_speaker" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -102,7 +102,6 @@
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="?attr/dividerColor" />
|
android:background="?attr/dividerColor" />
|
||||||
|
|
||||||
<!-- TODO: FIXME: Use AudioOnly layout -->
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -110,10 +109,10 @@
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:checked="@{conferenceViewModel.conferenceAudioOnlyDisplayMode}"
|
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.AUDIO_ONLY}"
|
||||||
android:drawableEnd="@drawable/icon_conference_layout_audio_only"
|
android:drawableEnd="@drawable/icon_conference_layout_audio_only"
|
||||||
android:drawableTint="?attr/voipDrawableColor"
|
android:drawableTint="?attr/voipDrawableColor"
|
||||||
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceLayout.Legacy)}"
|
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.AUDIO_ONLY)}"
|
||||||
android:text="@string/conference_display_mode_audio_only" />
|
android:text="@string/conference_display_mode_audio_only" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
<?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">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.voip.data.ConferenceParticipantDeviceData" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/voip_conference_audio_only_participant_cell_height">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:background="@drawable/shape_audio_only_remote_background"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/participant_avatar"
|
||||||
|
layout="@layout/voip_contact_avatar"
|
||||||
|
android:layout_width="@dimen/voip_conference_audio_only_participant_avatar_size"
|
||||||
|
android:layout_height="@dimen/voip_conference_audio_only_participant_avatar_size"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
app:data="@{data}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintHeight_max="200dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/participant_name"
|
||||||
|
style="@style/call_remote_name_font"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:text="@{data.contact.fullName ?? data.displayName, default=`Merry Brandybuck`}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/participant_avatar"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/call_remote_name_font"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:text="@string/conference_participant_paused"
|
||||||
|
android:visibility="@{data.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/participant_name"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/shape_conference_audio_only_border"
|
||||||
|
android:visibility="@{data.activeSpeaker ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@dimen/voip_conference_participant_mic_muted_icon_size_grid"
|
||||||
|
android:layout_height="@dimen/voip_conference_participant_mic_muted_icon_size_grid"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:background="@drawable/shape_button_disabled_background"
|
||||||
|
android:contentDescription="@string/content_description_conference_participant_mic_muted"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:src="@drawable/icon_mic_muted"
|
||||||
|
android:visibility="@{data.micMuted ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</layout>
|
|
@ -61,4 +61,6 @@
|
||||||
<dimen name="voip_dialog_button_max_width">137dp</dimen>
|
<dimen name="voip_dialog_button_max_width">137dp</dimen>
|
||||||
<dimen name="voip_contact_avatar_max_height">200dp</dimen>
|
<dimen name="voip_contact_avatar_max_height">200dp</dimen>
|
||||||
<dimen name="voip_numpad_button_max_size">60dp</dimen>
|
<dimen name="voip_numpad_button_max_size">60dp</dimen>
|
||||||
|
<dimen name="voip_conference_audio_only_participant_cell_height">60dp</dimen>
|
||||||
|
<dimen name="voip_conference_audio_only_participant_avatar_size">40dp</dimen>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue