Changes to reflect new conference API
Should fix various conference UI issues More UI fixes related to conference Fixes & improvements Fixed remove participant button invisible in dark mode API changes Handle conference enter and leave Fixed conference UI issues Small UI improvements Improve logging Improved paused conference cell Use isMe if participant added or removed is focus Update method names after changes to conference API
This commit is contained in:
parent
63205cb33f
commit
b803ae9a61
19 changed files with 506 additions and 371 deletions
|
@ -203,11 +203,17 @@ repositories {
|
|||
maven {
|
||||
name "local linphone-sdk maven repository"
|
||||
url file(LinphoneSdkBuildDir + '/maven_repository/')
|
||||
content {
|
||||
includeGroup "org.linphone"
|
||||
}
|
||||
}
|
||||
|
||||
maven {
|
||||
name "linphone.org maven repository"
|
||||
url "https://linphone.org/maven_repository"
|
||||
content {
|
||||
includeGroup "org.linphone"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,4 +292,4 @@ if (crashlyticsEnabled()) {
|
|||
assembleDebug.finalizedBy(uploadCrashlyticsSymbolFileDebug)
|
||||
packageDebugBundle.finalizedBy(uploadCrashlyticsSymbolFileDebug)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ abstract class ProximitySensorActivity : GenericActivity() {
|
|||
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { }
|
||||
|
||||
override fun onSensorChanged(event: SensorEvent) {
|
||||
if (event.timestamp == 0L) return
|
||||
if (event.timestamp == 0L || !proximitySensorEnabled) return
|
||||
if (isProximitySensorNearby(event)) {
|
||||
if (!proximityWakeLock.isHeld) {
|
||||
Log.i("[Proximity Sensor Activity] Acquiring proximity wake lock")
|
||||
|
@ -89,6 +89,12 @@ abstract class ProximitySensorActivity : GenericActivity() {
|
|||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
enableProximitySensor(false)
|
||||
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
protected fun enableProximitySensor(enable: Boolean) {
|
||||
if (!proximitySensorFound) {
|
||||
Log.w("[Proximity Sensor Activity] Couldn't find proximity sensor in this device, skipping")
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.linphone.LinphoneApplication.Companion.corePreferences
|
|||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.call.viewmodels.CallsViewModel
|
||||
import org.linphone.activities.call.viewmodels.ConferenceViewModel
|
||||
import org.linphone.activities.call.viewmodels.ControlsViewModel
|
||||
import org.linphone.activities.call.viewmodels.SharedCallViewModel
|
||||
import org.linphone.activities.main.MainActivity
|
||||
|
@ -51,6 +52,7 @@ import org.linphone.utils.PermissionHelper
|
|||
class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
|
||||
private lateinit var callsViewModel: CallsViewModel
|
||||
private lateinit var controlsViewModel: ControlsViewModel
|
||||
private lateinit var conferenceViewModel: ConferenceViewModel
|
||||
private lateinit var sharedViewModel: SharedCallViewModel
|
||||
|
||||
private var dialog: Dialog? = null
|
||||
|
@ -75,6 +77,9 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
|
|||
controlsViewModel = ViewModelProvider(this).get(ControlsViewModel::class.java)
|
||||
binding.controlsViewModel = controlsViewModel
|
||||
|
||||
conferenceViewModel = ViewModelProvider(this).get(ConferenceViewModel::class.java)
|
||||
binding.conferenceViewModel = conferenceViewModel
|
||||
|
||||
callsViewModel.currentCallViewModel.observe(viewLifecycleOwner, {
|
||||
if (it != null) {
|
||||
binding.activeCallTimer.base =
|
||||
|
|
|
@ -22,9 +22,8 @@ package org.linphone.activities.call.viewmodels
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Call
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.*
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.PermissionHelper
|
||||
|
||||
|
@ -35,10 +34,6 @@ class CallsViewModel : ViewModel() {
|
|||
|
||||
val pausedCalls = MutableLiveData<ArrayList<CallViewModel>>()
|
||||
|
||||
val conferenceCalls = MutableLiveData<ArrayList<CallViewModel>>()
|
||||
|
||||
val isConferencePaused = MutableLiveData<Boolean>()
|
||||
|
||||
val noMoreCallEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
@ -52,14 +47,9 @@ class CallsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
private val listener = object : CoreListenerStub() {
|
||||
override fun onCallStateChanged(
|
||||
core: Core,
|
||||
call: Call,
|
||||
state: Call.State,
|
||||
message: String
|
||||
) {
|
||||
callPausedByRemote.value = state == Call.State.PausedByRemote
|
||||
isConferencePaused.value = !coreContext.core.isInConference
|
||||
override fun onCallStateChanged(core: Core, call: Call, state: Call.State, message: String) {
|
||||
Log.i("[Calls VM] Call state changed: $state")
|
||||
callPausedByRemote.value = (state == Call.State.PausedByRemote) and (call.conference == null)
|
||||
|
||||
val currentCall = core.currentCall
|
||||
if (currentCall == null) {
|
||||
|
@ -71,14 +61,11 @@ class CallsViewModel : ViewModel() {
|
|||
if (state == Call.State.End || state == Call.State.Released || state == Call.State.Error) {
|
||||
if (core.callsNb == 0) {
|
||||
noMoreCallEvent.value = Event(true)
|
||||
conferenceCalls.value = arrayListOf()
|
||||
} else {
|
||||
removeCallFromPausedListIfPresent(call)
|
||||
removeCallFromConferenceIfPresent(call)
|
||||
}
|
||||
} else if (state == Call.State.Paused) {
|
||||
addCallToPausedList(call)
|
||||
removeCallFromConferenceIfPresent(call)
|
||||
} else if (state == Call.State.Resuming) {
|
||||
removeCallFromPausedListIfPresent(call)
|
||||
} else if (call.state == Call.State.UpdatedByRemote) {
|
||||
|
@ -91,16 +78,8 @@ class CallsViewModel : ViewModel() {
|
|||
call.deferUpdate()
|
||||
callUpdateEvent.value = Event(call)
|
||||
}
|
||||
} else {
|
||||
if (state == Call.State.StreamsRunning) {
|
||||
callUpdateEvent.value = Event(call)
|
||||
}
|
||||
|
||||
if (call.conference != null) {
|
||||
addCallToConferenceListIfNotAlreadyInIt(call)
|
||||
} else {
|
||||
removeCallFromConferenceIfPresent(call)
|
||||
}
|
||||
} else if (state == Call.State.StreamsRunning) {
|
||||
callUpdateEvent.value = Event(call)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,20 +91,14 @@ class CallsViewModel : ViewModel() {
|
|||
if (currentCall != null) {
|
||||
currentCallViewModel.value = CallViewModel(currentCall)
|
||||
}
|
||||
callPausedByRemote.value = currentCall?.state == Call.State.PausedByRemote
|
||||
isConferencePaused.value = !coreContext.core.isInConference
|
||||
|
||||
val conferenceList = arrayListOf<CallViewModel>()
|
||||
callPausedByRemote.value = currentCall?.state == Call.State.PausedByRemote
|
||||
|
||||
for (call in coreContext.core.calls) {
|
||||
if (call.state == Call.State.Paused || call.state == Call.State.Pausing) {
|
||||
addCallToPausedList(call)
|
||||
} else {
|
||||
if (call.conference != null) {
|
||||
conferenceList.add(CallViewModel(call))
|
||||
}
|
||||
}
|
||||
}
|
||||
conferenceCalls.value = conferenceList
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
@ -138,20 +111,6 @@ class CallsViewModel : ViewModel() {
|
|||
coreContext.answerCallVideoUpdateRequest(call, accept)
|
||||
}
|
||||
|
||||
fun pauseConference() {
|
||||
if (coreContext.core.isInConference) {
|
||||
coreContext.core.leaveConference()
|
||||
isConferencePaused.value = true
|
||||
}
|
||||
}
|
||||
|
||||
fun resumeConference() {
|
||||
if (!coreContext.core.isInConference) {
|
||||
coreContext.core.enterConference()
|
||||
isConferencePaused.value = false
|
||||
}
|
||||
}
|
||||
|
||||
fun takeScreenshot() {
|
||||
if (!PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
askWriteExternalStoragePermissionEvent.value = Event(true)
|
||||
|
@ -161,9 +120,17 @@ class CallsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
private fun addCallToPausedList(call: Call) {
|
||||
if (call.conference != null) return // Conference will be displayed as paused, no need to display the call as well
|
||||
|
||||
val list = arrayListOf<CallViewModel>()
|
||||
list.addAll(pausedCalls.value.orEmpty())
|
||||
|
||||
for (pausedCallViewModel in list) {
|
||||
if (pausedCallViewModel.call == call) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val viewModel = CallViewModel(call)
|
||||
list.add(viewModel)
|
||||
pausedCalls.value = list
|
||||
|
@ -182,31 +149,4 @@ class CallsViewModel : ViewModel() {
|
|||
|
||||
pausedCalls.value = list
|
||||
}
|
||||
|
||||
private fun addCallToConferenceListIfNotAlreadyInIt(call: Call) {
|
||||
val list = arrayListOf<CallViewModel>()
|
||||
list.addAll(conferenceCalls.value.orEmpty())
|
||||
|
||||
for (viewModel in list) {
|
||||
if (viewModel.call == call) return
|
||||
}
|
||||
|
||||
val viewModel = CallViewModel(call)
|
||||
list.add(viewModel)
|
||||
conferenceCalls.value = list
|
||||
}
|
||||
|
||||
private fun removeCallFromConferenceIfPresent(call: Call) {
|
||||
val list = arrayListOf<CallViewModel>()
|
||||
list.addAll(conferenceCalls.value.orEmpty())
|
||||
|
||||
for (viewModel in list) {
|
||||
if (viewModel.call == call) {
|
||||
list.remove(viewModel)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
conferenceCalls.value = list
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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.call.viewmodels
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.contact.GenericContactViewModel
|
||||
import org.linphone.core.Conference
|
||||
import org.linphone.core.Participant
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
class ConferenceParticipantViewModel(
|
||||
private val conference: Conference,
|
||||
val participant: Participant
|
||||
) :
|
||||
GenericContactViewModel(participant.address) {
|
||||
private val isAdmin = MutableLiveData<Boolean>()
|
||||
val isMeAdmin = MutableLiveData<Boolean>()
|
||||
|
||||
init {
|
||||
isAdmin.value = participant.isAdmin
|
||||
isMeAdmin.value = conference.me.isAdmin
|
||||
Log.i("[Conference Participant VM] Participant ${participant.address.asStringUriOnly()} is ${if (participant.isAdmin) "admin" else "not admin"}")
|
||||
Log.i("[Conference Participant VM] Me is ${if (conference.me.isAdmin) "admin" else "not admin"} and is ${if (conference.me.isFocus) "focus" else "not focus"}")
|
||||
}
|
||||
|
||||
fun removeFromConference() {
|
||||
Log.i("[Conference Participant VM] Removing participant ${participant.address.asStringUriOnly()} from conference $conference")
|
||||
conference.removeParticipant(participant)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 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.call.viewmodels
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.*
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
class ConferenceViewModel : ViewModel() {
|
||||
val isConferencePaused = MutableLiveData<Boolean>()
|
||||
|
||||
val isMeConferenceFocus = MutableLiveData<Boolean>()
|
||||
|
||||
val conferenceAddress = MutableLiveData<Address>()
|
||||
|
||||
val conferenceParticipants = MutableLiveData<List<ConferenceParticipantViewModel>>()
|
||||
|
||||
val isInConference = MutableLiveData<Boolean>()
|
||||
|
||||
private val conferenceListener = object : ConferenceListenerStub() {
|
||||
override fun onParticipantAdded(conference: Conference, participant: Participant) {
|
||||
if (conference.isMe(participant.address)) {
|
||||
Log.i("[Conference VM] Entered conference")
|
||||
isConferencePaused.value = false
|
||||
} else {
|
||||
Log.i("[Conference VM] Participant added")
|
||||
updateParticipantsList(conference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onParticipantRemoved(conference: Conference, participant: Participant) {
|
||||
if (conference.isMe(participant.address)) {
|
||||
Log.i("[Conference VM] Left conference")
|
||||
isConferencePaused.value = true
|
||||
} else {
|
||||
Log.i("[Conference VM] Participant removed")
|
||||
updateParticipantsList(conference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onParticipantAdminStatusChanged(
|
||||
conference: Conference,
|
||||
participant: Participant
|
||||
) {
|
||||
Log.i("[Conference VM] Participant admin status changed")
|
||||
updateParticipantsList(conference)
|
||||
}
|
||||
}
|
||||
|
||||
private val listener = object : CoreListenerStub() {
|
||||
override fun onConferenceStateChanged(
|
||||
core: Core,
|
||||
conference: Conference,
|
||||
state: Conference.State
|
||||
) {
|
||||
Log.i("[Conference VM] Conference state changed: $state")
|
||||
isConferencePaused.value = !conference.isIn
|
||||
|
||||
if (state == Conference.State.Instantiated) {
|
||||
conference.addListener(conferenceListener)
|
||||
} else if (state == Conference.State.Created) {
|
||||
updateParticipantsList(conference)
|
||||
isMeConferenceFocus.value = conference.me.isFocus
|
||||
conferenceAddress.value = conference.conferenceAddress
|
||||
} else if (state == Conference.State.Terminated || state == Conference.State.TerminationFailed) {
|
||||
isInConference.value = false
|
||||
conference.removeListener(conferenceListener)
|
||||
conferenceParticipants.value = arrayListOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
coreContext.core.addListener(listener)
|
||||
|
||||
isConferencePaused.value = coreContext.core.conference?.isIn != true
|
||||
isMeConferenceFocus.value = false
|
||||
conferenceParticipants.value = arrayListOf()
|
||||
isInConference.value = false
|
||||
|
||||
val conference = coreContext.core.conference
|
||||
if (conference != null) {
|
||||
conference.addListener(conferenceListener)
|
||||
isMeConferenceFocus.value = conference.me.isFocus
|
||||
updateParticipantsList(conference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
coreContext.core.removeListener(listener)
|
||||
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun pauseConference() {
|
||||
val defaultProxyConfig = coreContext.core.defaultProxyConfig
|
||||
val localAddress = defaultProxyConfig?.identityAddress
|
||||
val participants = arrayOf<Address>()
|
||||
val remoteConference = coreContext.core.searchConference(null, localAddress, conferenceAddress.value, participants)
|
||||
val localConference = coreContext.core.searchConference(null, conferenceAddress.value, conferenceAddress.value, participants)
|
||||
val conference = remoteConference ?: localConference
|
||||
|
||||
if (conference != null) {
|
||||
Log.i("[Conference VM] Leaving conference with address ${conferenceAddress.value?.asStringUriOnly()} temporarily")
|
||||
conference.leave()
|
||||
} else {
|
||||
Log.w("[Conference VM] Unable to find conference with address ${conferenceAddress.value?.asStringUriOnly()}")
|
||||
}
|
||||
}
|
||||
|
||||
fun resumeConference() {
|
||||
val defaultProxyConfig = coreContext.core.defaultProxyConfig
|
||||
val localAddress = defaultProxyConfig?.identityAddress
|
||||
val participants = arrayOf<Address>()
|
||||
val remoteConference = coreContext.core.searchConference(null, localAddress, conferenceAddress.value, participants)
|
||||
val localConference = coreContext.core.searchConference(null, conferenceAddress.value, conferenceAddress.value, participants)
|
||||
val conference = remoteConference ?: localConference
|
||||
|
||||
if (conference != null) {
|
||||
Log.i("[Conference VM] Entering again conference with address ${conferenceAddress.value?.asStringUriOnly()}")
|
||||
conference.enter()
|
||||
} else {
|
||||
Log.w("[Conference VM] Unable to find conference with address ${conferenceAddress.value?.asStringUriOnly()}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateParticipantsList(conference: Conference) {
|
||||
val participants = arrayListOf<ConferenceParticipantViewModel>()
|
||||
for (participant in conference.participantList) {
|
||||
Log.i("[Conference VM] Participant found: ${participant.address.asStringUriOnly()}")
|
||||
val viewModel = ConferenceParticipantViewModel(conference, participant)
|
||||
participants.add(viewModel)
|
||||
}
|
||||
conferenceParticipants.value = participants
|
||||
isInConference.value = participants.isNotEmpty()
|
||||
}
|
||||
}
|
|
@ -285,8 +285,8 @@ class ControlsViewModel : ViewModel() {
|
|||
|
||||
if (conference != null && core.isInConference) {
|
||||
val params = core.createConferenceParams()
|
||||
val videoEnabled = conference.currentParams.videoEnabled()
|
||||
params.enableVideo(!videoEnabled)
|
||||
val videoEnabled = conference.currentParams.isVideoEnabled
|
||||
params.isVideoEnabled = !videoEnabled
|
||||
Log.i("[Controls VM] Conference current param for video is $videoEnabled")
|
||||
conference.updateParams(params)
|
||||
} else if (currentCall != null) {
|
||||
|
@ -362,7 +362,7 @@ class ControlsViewModel : ViewModel() {
|
|||
val currentCallVideoEnabled = core.currentCall?.currentParams?.videoEnabled() ?: false
|
||||
|
||||
val params = core.createConferenceParams()
|
||||
params.enableVideo(currentCallVideoEnabled)
|
||||
params.isVideoEnabled = currentCallVideoEnabled
|
||||
Log.i("[Call] Setting videoEnabled to [$currentCallVideoEnabled] in conference params")
|
||||
|
||||
val conference = core.conference ?: core.createConferenceWithParams(params)
|
||||
|
|
|
@ -37,16 +37,8 @@ class StatisticsListViewModel : ViewModel() {
|
|||
state: Call.State,
|
||||
message: String
|
||||
) {
|
||||
if (state == Call.State.End || state == Call.State.Error) {
|
||||
val newList = arrayListOf<CallStatisticsData>()
|
||||
for (stat in callStatsList.value.orEmpty()) {
|
||||
if (stat.call != call) {
|
||||
newList.add(stat)
|
||||
} else {
|
||||
stat.destroy()
|
||||
}
|
||||
}
|
||||
callStatsList.value = newList
|
||||
if (state == Call.State.End || state == Call.State.Error || state == Call.State.Connected) {
|
||||
computeCallsList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,13 +46,7 @@ class StatisticsListViewModel : ViewModel() {
|
|||
init {
|
||||
coreContext.core.addListener(listener)
|
||||
|
||||
val list = arrayListOf<CallStatisticsData>()
|
||||
for (call in coreContext.core.calls) {
|
||||
if (call.state != Call.State.End && call.state != Call.State.Released && call.state != Call.State.Error) {
|
||||
list.add(CallStatisticsData(call))
|
||||
}
|
||||
}
|
||||
callStatsList.value = list
|
||||
computeCallsList()
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
@ -69,4 +55,14 @@ class StatisticsListViewModel : ViewModel() {
|
|||
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
private fun computeCallsList() {
|
||||
val list = arrayListOf<CallStatisticsData>()
|
||||
for (call in coreContext.core.calls) {
|
||||
if (call.state != Call.State.End && call.state != Call.State.Released && call.state != Call.State.Error) {
|
||||
list.add(CallStatisticsData(call))
|
||||
}
|
||||
}
|
||||
callStatsList.value = list
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ class StatusViewModel : StatusViewModel() {
|
|||
}
|
||||
|
||||
private fun updateCallQualityIcon() {
|
||||
val call = coreContext.core.currentCall
|
||||
val call = coreContext.core.currentCall ?: coreContext.core.calls.firstOrNull()
|
||||
val quality = call?.currentQuality ?: 0f
|
||||
callQualityIcon.value = when {
|
||||
quality >= 4 -> R.drawable.call_quality_indicator_4
|
||||
|
|
|
@ -26,11 +26,12 @@ import android.view.LayoutInflater
|
|||
import android.widget.LinearLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.call.viewmodels.CallViewModel
|
||||
import org.linphone.databinding.CallConferenceBinding
|
||||
import org.linphone.activities.call.viewmodels.ConferenceParticipantViewModel
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.CallConferenceParticipantBinding
|
||||
|
||||
class ConferenceCallView : LinearLayout {
|
||||
private lateinit var binding: CallConferenceBinding
|
||||
class ConferenceParticipantView : LinearLayout {
|
||||
private lateinit var binding: CallConferenceParticipantBinding
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
init(context)
|
||||
|
@ -53,15 +54,18 @@ class ConferenceCallView : LinearLayout {
|
|||
|
||||
fun init(context: Context) {
|
||||
binding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(context), R.layout.call_conference, this, true
|
||||
LayoutInflater.from(context), R.layout.call_conference_participant, this, true
|
||||
)
|
||||
}
|
||||
|
||||
fun setViewModel(viewModel: CallViewModel) {
|
||||
fun setViewModel(viewModel: ConferenceParticipantViewModel) {
|
||||
binding.viewModel = viewModel
|
||||
|
||||
binding.callTimer.base =
|
||||
SystemClock.elapsedRealtime() - (1000 * viewModel.call.duration) // Linphone timestamps are in seconds
|
||||
val currentTimeSecs = System.currentTimeMillis()
|
||||
val participantTime = viewModel.participant.creationTime * 1000 // Linphone timestamps are in seconds
|
||||
val diff = currentTimeSecs - participantTime
|
||||
Log.i("[Conference Participant] Participant joined conference at $participantTime == ${diff / 1000} seconds ago.")
|
||||
binding.callTimer.base = SystemClock.elapsedRealtime() - diff
|
||||
binding.callTimer.start()
|
||||
}
|
||||
}
|
|
@ -506,7 +506,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
fun isVideoCallOrConferenceActive(): Boolean {
|
||||
val conference = core.conference
|
||||
return if (conference != null && core.isInConference) {
|
||||
conference.currentParams.videoEnabled()
|
||||
conference.currentParams.isVideoEnabled()
|
||||
} else {
|
||||
core.currentCall?.currentParams?.videoEnabled() ?: false
|
||||
}
|
||||
|
|
7
app/src/main/res/drawable/conference.xml
Normal file
7
app/src/main/res/drawable/conference.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<bitmap android:src="@drawable/options_start_conference_default"
|
||||
android:tint="?attr/drawableTintColor2"/>
|
||||
</item>
|
||||
</selector>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<bitmap android:src="@drawable/conference_exit_default"
|
||||
android:tint="?attr/drawableTintColor"/>
|
||||
</item>
|
||||
</selector>
|
||||
|
|
@ -12,6 +12,9 @@
|
|||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ControlsViewModel" />
|
||||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ConferenceViewModel" />
|
||||
</data>
|
||||
|
||||
<RelativeLayout
|
||||
|
@ -26,7 +29,7 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@+id/active_call_header"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null || conferenceViewModel.isInConference() ? View.GONE : View.VISIBLE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
|
@ -54,75 +57,16 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="@{viewModel.conferenceCalls.size() == 0 || viewModel.isConferencePaused ? View.GONE : View.VISIBLE, default=gone}"
|
||||
<include layout="@layout/call_conference"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="?attr/backgroundColor"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="10dp"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="30sp"
|
||||
android:text="@string/call_conference_title" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/pause_conference"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:src="@drawable/camera_switch" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pause_conference"
|
||||
android:onClick="@{() -> viewModel.pauseConference()}"
|
||||
android:contentDescription="@string/content_description_pause_conference"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:src="@drawable/call_pause" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dividerColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:orientation="vertical"
|
||||
app:entries="@{viewModel.conferenceCalls}"
|
||||
app:layout="@{@layout/call_conference_cell}"/>
|
||||
|
||||
</LinearLayout>
|
||||
app:controlsViewModel="@{controlsViewModel}"
|
||||
app:conferenceViewModel="@{conferenceViewModel}" />
|
||||
|
||||
<org.linphone.contact.BigContactAvatarView
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled ? View.GONE : View.VISIBLE, default=gone}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled || conferenceViewModel.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
|
@ -169,51 +113,15 @@
|
|||
app:entries="@{viewModel.pausedCalls}"
|
||||
app:layout="@{@layout/call_paused_cell}" />
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="@{viewModel.isConferencePaused && viewModel.conferenceCalls.size() > 1 ? View.VISIBLE : View.GONE, default=gone}"
|
||||
<include layout="@layout/conference_paused"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_above="@id/paused_calls"
|
||||
android:alpha="0.5"
|
||||
android:background="?attr/accentColor"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:contentDescription="@string/content_description_start_conference"
|
||||
android:src="@drawable/options_start_conference" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical|left"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/call_conference_title" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.resumeConference()}"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center_vertical"
|
||||
android:contentDescription="@string/content_description_resume_conference"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/call_pause" />
|
||||
|
||||
</LinearLayout>
|
||||
app:conferenceViewModel="@{conferenceViewModel}" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.currentCallViewModel.pause()}"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null || conferenceViewModel.isInConference ? View.GONE : View.VISIBLE}"
|
||||
android:selected="@{viewModel.currentCallViewModel.isPaused ?? false}"
|
||||
android:enabled="@{!viewModel.callPausedByRemote && controlsViewModel.isPauseEnabled}"
|
||||
android:contentDescription="@string/content_description_pause_call"
|
||||
|
@ -230,7 +138,7 @@
|
|||
android:id="@+id/switch_camera"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:enabled="@{!viewModel.callPausedByRemote}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.showSwitchCamera && (viewModel.conferenceCalls.size() == 0 || viewModel.isConferencePaused) ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.showSwitchCamera && !conferenceViewModel.isInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
|
@ -244,7 +152,7 @@
|
|||
<ImageView
|
||||
android:onClick="@{() -> viewModel.takeScreenshot()}"
|
||||
android:enabled="@{!viewModel.callPausedByRemote}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.takeScreenshotEnabled && (viewModel.conferenceCalls.size() == 0 || viewModel.isConferencePaused) ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.takeScreenshotEnabled && !conferenceViewModel.isInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_take_screenshot"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
|
|
|
@ -1,79 +1,89 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
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="viewModel"
|
||||
type="org.linphone.activities.call.viewmodels.CallViewModel" />
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ControlsViewModel" />
|
||||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ConferenceViewModel" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="@{!conferenceViewModel.isInConference || conferenceViewModel.isConferencePaused ? View.GONE : View.VISIBLE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/backgroundColor"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="10dp">
|
||||
android:layout_height="60dp">
|
||||
|
||||
<org.linphone.contact.ContactAvatarView
|
||||
android:id="@+id/avatar"
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
app:viewModel="@{viewModel}"
|
||||
tools:layout="@layout/contact_avatar" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="10dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.linphone.views.MarqueeTextView
|
||||
android:text="@{viewModel.contact.fullName ?? viewModel.displayName}"
|
||||
style="@style/contact_name_list_cell_font"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|left"
|
||||
android:singleLine="true"/>
|
||||
|
||||
<Chronometer
|
||||
android:id="@+id/call_timer"
|
||||
android:textColor="?attr/accentColor"
|
||||
android:textSize="16sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|right" />
|
||||
|
||||
</LinearLayout>
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="10dp"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="30sp"
|
||||
android:text="@string/call_conference_title" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.removeFromConference()}"
|
||||
android:contentDescription="@string/content_description_remove_from_conference"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled ? View.VISIBLE : View.GONE}"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_toLeftOf="@id/pause_conference"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:gravity="center_vertical"
|
||||
android:src="@drawable/conference_exit_default" />
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:src="@drawable/camera_switch" />
|
||||
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/pause_conference"
|
||||
android:onClick="@{() -> conferenceViewModel.pauseConference()}"
|
||||
android:contentDescription="@string/content_description_pause_conference"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:src="@drawable/call_pause" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dividerColor" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:entries="@{conferenceViewModel.conferenceParticipants}"
|
||||
app:layout="@{@layout/call_conference_cell}"/>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
|
@ -5,10 +5,10 @@
|
|||
<data>
|
||||
<variable
|
||||
name="data"
|
||||
type="org.linphone.activities.call.viewmodels.CallViewModel" />
|
||||
type="org.linphone.activities.call.viewmodels.ConferenceParticipantViewModel" />
|
||||
</data>
|
||||
|
||||
<org.linphone.activities.call.views.ConferenceCallView
|
||||
<org.linphone.activities.call.views.ConferenceParticipantView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
bind:viewModel="@{data}"/>
|
||||
|
|
80
app/src/main/res/layout/call_conference_participant.xml
Normal file
80
app/src/main/res/layout/call_conference_participant.xml
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ConferenceParticipantViewModel" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:layout_margin="10dp">
|
||||
|
||||
<org.linphone.contact.ContactAvatarView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
app:viewModel="@{viewModel}"
|
||||
tools:layout="@layout/contact_avatar" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="10dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.linphone.views.MarqueeTextView
|
||||
android:text="@{viewModel.contact.fullName ?? viewModel.displayName}"
|
||||
style="@style/contact_name_list_cell_font"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|left"
|
||||
android:singleLine="true"/>
|
||||
|
||||
<Chronometer
|
||||
android:id="@+id/call_timer"
|
||||
android:textColor="?attr/accentColor"
|
||||
android:textSize="16sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical|right" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.removeFromConference()}"
|
||||
android:visibility="@{viewModel.isMeAdmin ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_remove_from_conference"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:adjustViewBounds="true"
|
||||
android:gravity="center_vertical"
|
||||
android:src="@drawable/conference_remove_participant" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dividerColor" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
|
@ -11,6 +11,9 @@
|
|||
<variable
|
||||
name="controlsViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ControlsViewModel" />
|
||||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ConferenceViewModel" />
|
||||
</data>
|
||||
|
||||
<RelativeLayout
|
||||
|
@ -25,7 +28,7 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@+id/active_call_header"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null || conferenceViewModel.isInConference() ? View.GONE : View.VISIBLE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
|
@ -53,75 +56,16 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="@{viewModel.conferenceCalls.size() == 0 || viewModel.isConferencePaused ? View.GONE : View.VISIBLE, default=gone}"
|
||||
<include layout="@layout/call_conference"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="?attr/backgroundColor"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="10dp"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="30sp"
|
||||
android:text="@string/call_conference_title" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/pause_conference"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:src="@drawable/camera_switch" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pause_conference"
|
||||
android:onClick="@{() -> viewModel.pauseConference()}"
|
||||
android:contentDescription="@string/content_description_pause_conference"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:padding="10dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:src="@drawable/call_pause" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dividerColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:orientation="vertical"
|
||||
app:entries="@{viewModel.conferenceCalls}"
|
||||
app:layout="@{@layout/call_conference_cell}"/>
|
||||
|
||||
</LinearLayout>
|
||||
app:controlsViewModel="@{controlsViewModel}"
|
||||
app:conferenceViewModel="@{conferenceViewModel}" />
|
||||
|
||||
<org.linphone.contact.BigContactAvatarView
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled ? View.GONE : View.VISIBLE, default=gone}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled || conferenceViewModel.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
|
@ -148,7 +92,7 @@
|
|||
android:src="@drawable/waiting_time" />
|
||||
|
||||
<TextView
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
android:textColor="@color/white_color"
|
||||
android:textSize="15sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -169,51 +113,15 @@
|
|||
app:entries="@{viewModel.pausedCalls}"
|
||||
app:layout="@{@layout/call_paused_cell}" />
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="@{viewModel.isConferencePaused && viewModel.conferenceCalls.size() > 1 ? View.VISIBLE : View.GONE, default=gone}"
|
||||
<include layout="@layout/conference_paused"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_above="@id/paused_calls"
|
||||
android:alpha="0.5"
|
||||
android:background="?attr/accentColor"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:contentDescription="@string/content_description_start_conference"
|
||||
android:src="@drawable/options_start_conference" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical|left"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/call_conference_title" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.resumeConference()}"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center_vertical"
|
||||
android:contentDescription="@string/content_description_resume_conference"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/call_pause" />
|
||||
|
||||
</LinearLayout>
|
||||
app:conferenceViewModel="@{conferenceViewModel}" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.currentCallViewModel.pause()}"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.currentCallViewModel == null || conferenceViewModel.isInConference ? View.GONE : View.VISIBLE}"
|
||||
android:selected="@{viewModel.currentCallViewModel.isPaused ?? false}"
|
||||
android:enabled="@{!viewModel.callPausedByRemote && controlsViewModel.isPauseEnabled}"
|
||||
android:contentDescription="@string/content_description_pause_call"
|
||||
|
@ -230,7 +138,7 @@
|
|||
android:id="@+id/switch_camera"
|
||||
android:onClick="@{() -> controlsViewModel.switchCamera()}"
|
||||
android:enabled="@{!viewModel.callPausedByRemote}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.showSwitchCamera && (viewModel.conferenceCalls.size() == 0 || viewModel.isConferencePaused) ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.showSwitchCamera && !conferenceViewModel.isInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_switch_camera"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
|
@ -244,7 +152,7 @@
|
|||
<ImageView
|
||||
android:onClick="@{() -> viewModel.takeScreenshot()}"
|
||||
android:enabled="@{!viewModel.callPausedByRemote}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.takeScreenshotEnabled && (viewModel.conferenceCalls.size() == 0 || viewModel.isConferencePaused) ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{controlsViewModel.isVideoEnabled && controlsViewModel.takeScreenshotEnabled && !conferenceViewModel.isInConference ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:contentDescription="@string/content_description_take_screenshot"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
|
|
54
app/src/main/res/layout/conference_paused.xml
Normal file
54
app/src/main/res/layout/conference_paused.xml
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.activities.call.viewmodels.ConferenceViewModel" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="@{conferenceViewModel.isConferencePaused && conferenceViewModel.isInConference ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:alpha="0.5"
|
||||
android:background="?attr/accentColor"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="5dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="5dp"
|
||||
android:contentDescription="@string/content_description_start_conference"
|
||||
android:src="@drawable/conference" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical|left"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
android:textSize="21sp"
|
||||
android:text="@string/call_conference_title" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> conferenceViewModel.resumeConference()}"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center_vertical"
|
||||
android:contentDescription="@string/content_description_resume_conference"
|
||||
android:background="@drawable/round_button_background"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/call_pause" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
Loading…
Reference in a new issue