Added broadcast mode for scheduled conferences
This commit is contained in:
parent
2334a0e6a8
commit
4b27d1180a
29 changed files with 660 additions and 50 deletions
|
@ -63,6 +63,8 @@ class ChatMessageContentData(
|
||||||
val isConferenceSchedule = MutableLiveData<Boolean>()
|
val isConferenceSchedule = MutableLiveData<Boolean>()
|
||||||
val isConferenceUpdated = MutableLiveData<Boolean>()
|
val isConferenceUpdated = MutableLiveData<Boolean>()
|
||||||
val isConferenceCancelled = MutableLiveData<Boolean>()
|
val isConferenceCancelled = MutableLiveData<Boolean>()
|
||||||
|
val isBroadcast = MutableLiveData<Boolean>()
|
||||||
|
val isSpeaker = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val fileName = MutableLiveData<String>()
|
val fileName = MutableLiveData<String>()
|
||||||
val filePath = MutableLiveData<String>()
|
val filePath = MutableLiveData<String>()
|
||||||
|
@ -378,14 +380,26 @@ class ChatMessageContentData(
|
||||||
var participantsCount = conferenceInfo.participants.size
|
var participantsCount = conferenceInfo.participants.size
|
||||||
val organizer = conferenceInfo.organizer
|
val organizer = conferenceInfo.organizer
|
||||||
var organizerFound = false
|
var organizerFound = false
|
||||||
if (organizer != null) {
|
var allSpeaker = true
|
||||||
for (participant in conferenceInfo.participants) {
|
isSpeaker.value = true
|
||||||
|
for (info in conferenceInfo.participantInfos) {
|
||||||
|
val participant = info.address
|
||||||
|
if (participant.weakEqual(chatMessage.chatRoom.localAddress)) {
|
||||||
|
isSpeaker.value = info.role == Participant.Role.Speaker
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.role == Participant.Role.Listener) {
|
||||||
|
allSpeaker = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (organizer != null) {
|
||||||
if (participant.weakEqual(organizer)) {
|
if (participant.weakEqual(organizer)) {
|
||||||
organizerFound = true
|
organizerFound = true
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isBroadcast.value = allSpeaker == false
|
||||||
|
|
||||||
if (!organizerFound) participantsCount += 1 // +1 for organizer
|
if (!organizerFound) participantsCount += 1 // +1 for organizer
|
||||||
conferenceParticipantCount.value = String.format(
|
conferenceParticipantCount.value = String.format(
|
||||||
AppUtils.getString(R.string.conference_invite_participants_count),
|
AppUtils.getString(R.string.conference_invite_participants_count),
|
||||||
|
|
|
@ -19,15 +19,35 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.main.conference.data
|
package org.linphone.activities.main.conference.data
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.contact.GenericContactData
|
import org.linphone.contact.GenericContactData
|
||||||
import org.linphone.core.Address
|
import org.linphone.core.Address
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
|
||||||
class ConferenceSchedulingParticipantData(
|
class ConferenceSchedulingParticipantData(
|
||||||
private val sipAddress: Address,
|
val sipAddress: Address,
|
||||||
val showLimeBadge: Boolean = false,
|
val showLimeBadge: Boolean = false,
|
||||||
val showDivider: Boolean = true
|
val showDivider: Boolean = true,
|
||||||
|
val showBroadcastControls: Boolean = false,
|
||||||
|
val speaker: Boolean = false,
|
||||||
|
private val onAddedToSpeakers: ((data: ConferenceSchedulingParticipantData) -> Unit)? = null,
|
||||||
|
private val onRemovedFromSpeakers: ((data: ConferenceSchedulingParticipantData) -> Unit)? = null
|
||||||
) :
|
) :
|
||||||
GenericContactData(sipAddress) {
|
GenericContactData(sipAddress) {
|
||||||
|
val isSpeaker = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val sipUri: String get() = LinphoneUtils.getDisplayableAddress(sipAddress)
|
val sipUri: String get() = LinphoneUtils.getDisplayableAddress(sipAddress)
|
||||||
|
|
||||||
|
init {
|
||||||
|
isSpeaker.value = speaker
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeIsSpeaker() {
|
||||||
|
isSpeaker.value = isSpeaker.value == false
|
||||||
|
if (isSpeaker.value == true) {
|
||||||
|
onAddedToSpeakers?.invoke(this)
|
||||||
|
} else {
|
||||||
|
onRemovedFromSpeakers?.invoke(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.core.ConferenceInfo
|
import org.linphone.core.ConferenceInfo
|
||||||
import org.linphone.core.ConferenceInfo.State
|
import org.linphone.core.ConferenceInfo.State
|
||||||
|
import org.linphone.core.Participant
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
import org.linphone.utils.TimestampUtils
|
import org.linphone.utils.TimestampUtils
|
||||||
|
@ -45,9 +46,12 @@ class ScheduledConferenceData(val conferenceInfo: ConferenceInfo, private val is
|
||||||
val participantsExpanded = MutableLiveData<String>()
|
val participantsExpanded = MutableLiveData<String>()
|
||||||
val showDuration = MutableLiveData<Boolean>()
|
val showDuration = MutableLiveData<Boolean>()
|
||||||
val isConferenceCancelled = MutableLiveData<Boolean>()
|
val isConferenceCancelled = MutableLiveData<Boolean>()
|
||||||
|
val isBroadcast = MutableLiveData<Boolean>()
|
||||||
|
val speakersExpanded = MutableLiveData<String>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
expanded.value = false
|
expanded.value = false
|
||||||
|
isBroadcast.value = false
|
||||||
|
|
||||||
address.value = conferenceInfo.uri?.asStringUriOnly()
|
address.value = conferenceInfo.uri?.asStringUriOnly()
|
||||||
subject.value = conferenceInfo.subject
|
subject.value = conferenceInfo.subject
|
||||||
|
@ -141,24 +145,48 @@ class ScheduledConferenceData(val conferenceInfo: ConferenceInfo, private val is
|
||||||
private fun computeParticipantsLists() {
|
private fun computeParticipantsLists() {
|
||||||
var participantsListShort = ""
|
var participantsListShort = ""
|
||||||
var participantsListExpanded = ""
|
var participantsListExpanded = ""
|
||||||
|
var speakersListExpanded = ""
|
||||||
|
|
||||||
|
var allSpeaker = true
|
||||||
|
for (info in conferenceInfo.participantInfos) {
|
||||||
|
val participant = info.address
|
||||||
|
Log.i(
|
||||||
|
"[Scheduled Conference] Conference [${subject.value}] participant [${participant.asStringUriOnly()}] is a [${info.role}]"
|
||||||
|
)
|
||||||
|
|
||||||
for (participant in conferenceInfo.participants) {
|
|
||||||
val contact = coreContext.contactsManager.findContactByAddress(participant)
|
val contact = coreContext.contactsManager.findContactByAddress(participant)
|
||||||
val name = if (contact != null) {
|
val name = if (contact != null) {
|
||||||
contact.name
|
contact.name
|
||||||
} else {
|
} else {
|
||||||
LinphoneUtils.getDisplayName(
|
LinphoneUtils.getDisplayName(participant)
|
||||||
participant
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
val address = participant.asStringUriOnly()
|
val address = participant.asStringUriOnly()
|
||||||
participantsListShort += "$name, "
|
participantsListShort += "$name, "
|
||||||
participantsListExpanded += "$name ($address)\n"
|
when (info.role) {
|
||||||
|
Participant.Role.Speaker -> {
|
||||||
|
speakersListExpanded += "$name ($address)\n"
|
||||||
|
}
|
||||||
|
Participant.Role.Listener -> {
|
||||||
|
participantsListExpanded += "$name ($address)\n"
|
||||||
|
allSpeaker = false
|
||||||
|
}
|
||||||
|
else -> { // For meetings created before 5.3 SDK
|
||||||
|
participantsListExpanded += "$name ($address)\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
participantsListShort = participantsListShort.dropLast(2)
|
participantsListShort = participantsListShort.dropLast(2)
|
||||||
participantsListExpanded = participantsListExpanded.dropLast(1)
|
participantsListExpanded = participantsListExpanded.dropLast(1)
|
||||||
|
speakersListExpanded = speakersListExpanded.dropLast(1)
|
||||||
|
|
||||||
participantsShort.value = participantsListShort
|
participantsShort.value = participantsListShort
|
||||||
participantsExpanded.value = participantsListExpanded
|
participantsExpanded.value = participantsListExpanded
|
||||||
|
speakersExpanded.value = speakersListExpanded
|
||||||
|
|
||||||
|
// If all participants have Speaker role then it is a meeting, else it is a broadcast
|
||||||
|
isBroadcast.value = allSpeaker == false
|
||||||
|
Log.i(
|
||||||
|
"[Scheduled Conference] Conference [${subject.value}] is a ${if (allSpeaker) "meeting" else "broadcast"}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,9 @@ class ConferenceWaitingRoomFragment : GenericFragment<ConferenceWaitingRoomFragm
|
||||||
val conferenceSubject = arguments?.getString("Subject")
|
val conferenceSubject = arguments?.getString("Subject")
|
||||||
viewModel.subject.value = conferenceSubject
|
viewModel.subject.value = conferenceSubject
|
||||||
|
|
||||||
|
val address = arguments?.getString("Address")
|
||||||
|
viewModel.findConferenceInfoByAddress(address)
|
||||||
|
|
||||||
viewModel.cancelConferenceJoiningEvent.observe(
|
viewModel.cancelConferenceJoiningEvent.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import androidx.lifecycle.MediatorLiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.activities.main.conference.data.ConferenceSchedulingParticipantData
|
import org.linphone.activities.main.conference.data.ConferenceSchedulingParticipantData
|
||||||
import org.linphone.activities.main.conference.data.Duration
|
import org.linphone.activities.main.conference.data.Duration
|
||||||
|
@ -30,6 +31,7 @@ import org.linphone.activities.main.conference.data.TimeZoneData
|
||||||
import org.linphone.contact.ContactsSelectionViewModel
|
import org.linphone.contact.ContactsSelectionViewModel
|
||||||
import org.linphone.core.*
|
import org.linphone.core.*
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
|
import org.linphone.utils.AppUtils
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
import org.linphone.utils.TimestampUtils
|
import org.linphone.utils.TimestampUtils
|
||||||
|
@ -41,6 +43,10 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
val scheduleForLater = MutableLiveData<Boolean>()
|
val scheduleForLater = MutableLiveData<Boolean>()
|
||||||
val isUpdate = MutableLiveData<Boolean>()
|
val isUpdate = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val isBroadcastAllowed = MutableLiveData<Boolean>()
|
||||||
|
val mode = MutableLiveData<String>()
|
||||||
|
val modesList: List<String>
|
||||||
|
|
||||||
val formattedDate = MutableLiveData<String>()
|
val formattedDate = MutableLiveData<String>()
|
||||||
val formattedTime = MutableLiveData<String>()
|
val formattedTime = MutableLiveData<String>()
|
||||||
|
|
||||||
|
@ -50,6 +56,7 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
val sendInviteViaEmail = MutableLiveData<Boolean>()
|
val sendInviteViaEmail = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val participantsData = MutableLiveData<List<ConferenceSchedulingParticipantData>>()
|
val participantsData = MutableLiveData<List<ConferenceSchedulingParticipantData>>()
|
||||||
|
val speakersData = MutableLiveData<List<ConferenceSchedulingParticipantData>>()
|
||||||
|
|
||||||
val address = MutableLiveData<Address>()
|
val address = MutableLiveData<Address>()
|
||||||
|
|
||||||
|
@ -74,6 +81,8 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
private var confInfo: ConferenceInfo? = null
|
private var confInfo: ConferenceInfo? = null
|
||||||
private val conferenceScheduler = coreContext.core.createConferenceScheduler()
|
private val conferenceScheduler = coreContext.core.createConferenceScheduler()
|
||||||
|
|
||||||
|
private val selectedSpeakersAddresses = MutableLiveData<ArrayList<Address>>()
|
||||||
|
|
||||||
private val listener = object : ConferenceSchedulerListenerStub() {
|
private val listener = object : ConferenceSchedulerListenerStub() {
|
||||||
override fun onStateChanged(
|
override fun onStateChanged(
|
||||||
conferenceScheduler: ConferenceScheduler,
|
conferenceScheduler: ConferenceScheduler,
|
||||||
|
@ -154,6 +163,13 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
scheduleForLater.value = false
|
scheduleForLater.value = false
|
||||||
isUpdate.value = false
|
isUpdate.value = false
|
||||||
|
|
||||||
|
isBroadcastAllowed.value = !corePreferences.disableBroadcastConference
|
||||||
|
modesList = arrayListOf(
|
||||||
|
AppUtils.getString(R.string.conference_schedule_mode_meeting),
|
||||||
|
AppUtils.getString(R.string.conference_schedule_mode_broadcast)
|
||||||
|
)
|
||||||
|
mode.value = modesList.first() // Meeting by default
|
||||||
|
|
||||||
isEncrypted.value = false
|
isEncrypted.value = false
|
||||||
sendInviteViaChat.value = true
|
sendInviteViaChat.value = true
|
||||||
sendInviteViaEmail.value = false
|
sendInviteViaEmail.value = false
|
||||||
|
@ -185,6 +201,7 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
conferenceScheduler.removeListener(listener)
|
conferenceScheduler.removeListener(listener)
|
||||||
participantsData.value.orEmpty().forEach(ConferenceSchedulingParticipantData::destroy)
|
participantsData.value.orEmpty().forEach(ConferenceSchedulingParticipantData::destroy)
|
||||||
|
speakersData.value.orEmpty().forEach(ConferenceSchedulingParticipantData::destroy)
|
||||||
|
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
}
|
}
|
||||||
|
@ -195,6 +212,7 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun populateFromConferenceInfo(conferenceInfo: ConferenceInfo) {
|
fun populateFromConferenceInfo(conferenceInfo: ConferenceInfo) {
|
||||||
|
// Pre-set data from existing conference info, used when editing an already scheduled broadcast or meeting
|
||||||
confInfo = conferenceInfo
|
confInfo = conferenceInfo
|
||||||
|
|
||||||
address.value = conferenceInfo.uri
|
address.value = conferenceInfo.uri
|
||||||
|
@ -213,10 +231,26 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
scheduleForLater.value = conferenceDuration > 0
|
scheduleForLater.value = conferenceDuration > 0
|
||||||
|
|
||||||
val participantsList = arrayListOf<Address>()
|
val participantsList = arrayListOf<Address>()
|
||||||
for (participant in conferenceInfo.participants) {
|
val speakersList = arrayListOf<Address>()
|
||||||
|
for (info in conferenceInfo.participantInfos) {
|
||||||
|
val participant = info.address
|
||||||
participantsList.add(participant)
|
participantsList.add(participant)
|
||||||
|
if (info.role == Participant.Role.Speaker) {
|
||||||
|
speakersList.add(participant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (participantsList.count() == speakersList.count()) {
|
||||||
|
// All participants are speaker, this is a meeting, clear speakers
|
||||||
|
Log.i("[Conference Creation] Conference info is a meeting")
|
||||||
|
speakersList.clear()
|
||||||
|
mode.value = modesList.first()
|
||||||
|
} else {
|
||||||
|
Log.i("[Conference Creation] Conference info is a broadcast")
|
||||||
|
mode.value = modesList.last()
|
||||||
}
|
}
|
||||||
selectedAddresses.value = participantsList
|
selectedAddresses.value = participantsList
|
||||||
|
selectedSpeakersAddresses.value = speakersList
|
||||||
|
|
||||||
computeParticipantsData()
|
computeParticipantsData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,14 +275,57 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
|
|
||||||
fun computeParticipantsData() {
|
fun computeParticipantsData() {
|
||||||
participantsData.value.orEmpty().forEach(ConferenceSchedulingParticipantData::destroy)
|
participantsData.value.orEmpty().forEach(ConferenceSchedulingParticipantData::destroy)
|
||||||
val list = arrayListOf<ConferenceSchedulingParticipantData>()
|
speakersData.value.orEmpty().forEach(ConferenceSchedulingParticipantData::destroy)
|
||||||
|
|
||||||
|
val participantsList = arrayListOf<ConferenceSchedulingParticipantData>()
|
||||||
|
val speakersList = arrayListOf<ConferenceSchedulingParticipantData>()
|
||||||
|
|
||||||
for (address in selectedAddresses.value.orEmpty()) {
|
for (address in selectedAddresses.value.orEmpty()) {
|
||||||
val data = ConferenceSchedulingParticipantData(address, isEncrypted.value == true)
|
val isSpeaker = address in selectedSpeakersAddresses.value.orEmpty()
|
||||||
list.add(data)
|
val data = ConferenceSchedulingParticipantData(
|
||||||
|
address,
|
||||||
|
showLimeBadge = isEncrypted.value == true,
|
||||||
|
showBroadcastControls = isModeBroadcastCurrentlySelected(),
|
||||||
|
speaker = isSpeaker,
|
||||||
|
onAddedToSpeakers = { data ->
|
||||||
|
Log.i(
|
||||||
|
"[Conference Creation] Participant [${address.asStringUriOnly()}] added to speakers"
|
||||||
|
)
|
||||||
|
val participants = arrayListOf<ConferenceSchedulingParticipantData>()
|
||||||
|
participants.addAll(participantsData.value.orEmpty())
|
||||||
|
participants.remove(data)
|
||||||
|
participantsData.value = participants
|
||||||
|
|
||||||
|
val speakers = arrayListOf<ConferenceSchedulingParticipantData>()
|
||||||
|
speakers.addAll(speakersData.value.orEmpty())
|
||||||
|
speakers.add(data)
|
||||||
|
speakersData.value = speakers
|
||||||
|
},
|
||||||
|
onRemovedFromSpeakers = { data ->
|
||||||
|
Log.i(
|
||||||
|
"[Conference Creation] Participant [${address.asStringUriOnly()}] removed from speakers"
|
||||||
|
)
|
||||||
|
val speakers = arrayListOf<ConferenceSchedulingParticipantData>()
|
||||||
|
speakers.addAll(speakersData.value.orEmpty())
|
||||||
|
speakers.remove(data)
|
||||||
|
speakersData.value = speakers
|
||||||
|
|
||||||
|
val participants = arrayListOf<ConferenceSchedulingParticipantData>()
|
||||||
|
participants.addAll(participantsData.value.orEmpty())
|
||||||
|
participants.add(data)
|
||||||
|
participantsData.value = participants
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isSpeaker) {
|
||||||
|
speakersList.add(data)
|
||||||
|
} else {
|
||||||
|
participantsList.add(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
participantsData.value = list
|
participantsData.value = participantsList
|
||||||
|
speakersData.value = speakersList
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createConference() {
|
fun createConference() {
|
||||||
|
@ -260,8 +337,6 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
|
|
||||||
conferenceCreationInProgress.value = true
|
conferenceCreationInProgress.value = true
|
||||||
val core = coreContext.core
|
val core = coreContext.core
|
||||||
val participants = arrayOfNulls<Address>(selectedAddresses.value.orEmpty().size)
|
|
||||||
selectedAddresses.value?.toArray(participants)
|
|
||||||
val localAccount = core.defaultAccount
|
val localAccount = core.defaultAccount
|
||||||
val localAddress = localAccount?.params?.identityAddress
|
val localAddress = localAccount?.params?.identityAddress
|
||||||
|
|
||||||
|
@ -273,7 +348,25 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
conferenceInfo.organizer = localAddress
|
conferenceInfo.organizer = localAddress
|
||||||
conferenceInfo.subject = subject.value
|
conferenceInfo.subject = subject.value
|
||||||
conferenceInfo.description = description.value
|
conferenceInfo.description = description.value
|
||||||
conferenceInfo.setParticipants(participants)
|
|
||||||
|
val participants = arrayOfNulls<ParticipantInfo>(selectedAddresses.value.orEmpty().size)
|
||||||
|
var index = 0
|
||||||
|
val isBroadcast = isModeBroadcastCurrentlySelected()
|
||||||
|
for (participant in participantsData.value.orEmpty()) {
|
||||||
|
val info = Factory.instance().createParticipantInfo(participant.sipAddress)
|
||||||
|
// For meetings, all participants must have Speaker role
|
||||||
|
info?.role = if (isBroadcast) Participant.Role.Listener else Participant.Role.Speaker
|
||||||
|
participants[index] = info
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
for (speaker in speakersData.value.orEmpty()) {
|
||||||
|
val info = Factory.instance().createParticipantInfo(speaker.sipAddress)
|
||||||
|
info?.role = Participant.Role.Speaker
|
||||||
|
participants[index] = info
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
conferenceInfo.setParticipantInfos(participants)
|
||||||
|
|
||||||
if (scheduleForLater.value == true) {
|
if (scheduleForLater.value == true) {
|
||||||
val startTime = getConferenceStartTimestamp()
|
val startTime = getConferenceStartTimestamp()
|
||||||
conferenceInfo.dateTime = startTime
|
conferenceInfo.dateTime = startTime
|
||||||
|
@ -287,6 +380,10 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
||||||
conferenceScheduler.info = conferenceInfo
|
conferenceScheduler.info = conferenceInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isModeBroadcastCurrentlySelected(): Boolean {
|
||||||
|
return mode.value == AppUtils.getString(R.string.conference_schedule_mode_broadcast)
|
||||||
|
}
|
||||||
|
|
||||||
private fun computeTimeZonesList(): List<TimeZoneData> {
|
private fun computeTimeZonesList(): List<TimeZoneData> {
|
||||||
return TimeZone.getAvailableIDs().map { id -> TimeZoneData(TimeZone.getTimeZone(id)) }.toList().sorted()
|
return TimeZone.getAvailableIDs().map { id -> TimeZoneData(TimeZone.getTimeZone(id)) }.toList().sorted()
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ class ConferenceWaitingRoomViewModel : MessageNotifierViewModel() {
|
||||||
|
|
||||||
val networkReachable = MutableLiveData<Boolean>()
|
val networkReachable = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val isConferenceBroadcastWithListenerRole = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val askPermissionEvent: MutableLiveData<Event<String>> by lazy {
|
val askPermissionEvent: MutableLiveData<Event<String>> by lazy {
|
||||||
MutableLiveData<Event<String>>()
|
MutableLiveData<Event<String>>()
|
||||||
}
|
}
|
||||||
|
@ -198,7 +200,10 @@ class ConferenceWaitingRoomViewModel : MessageNotifierViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
layoutMenuSelected.value = false
|
layoutMenuSelected.value = false
|
||||||
updateLayout()
|
when (core.defaultConferenceLayout) {
|
||||||
|
Conference.Layout.Grid -> setMosaicLayout()
|
||||||
|
else -> setActiveSpeakerLayout()
|
||||||
|
}
|
||||||
|
|
||||||
if (AudioRouteUtils.isBluetoothAudioRouteAvailable()) {
|
if (AudioRouteUtils.isBluetoothAudioRouteAvailable()) {
|
||||||
setBluetoothAudioRoute()
|
setBluetoothAudioRoute()
|
||||||
|
@ -216,6 +221,44 @@ class ConferenceWaitingRoomViewModel : MessageNotifierViewModel() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun findConferenceInfoByAddress(stringAddress: String?) {
|
||||||
|
if (stringAddress != null) {
|
||||||
|
val address = Factory.instance().createAddress(stringAddress)
|
||||||
|
if (address != null) {
|
||||||
|
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(address)
|
||||||
|
if (conferenceInfo != null) {
|
||||||
|
val myself = conferenceInfo.participantInfos.find {
|
||||||
|
it.address.asStringUriOnly() == coreContext.core.defaultAccount?.params?.identityAddress?.asStringUriOnly()
|
||||||
|
}
|
||||||
|
if (myself != null) {
|
||||||
|
Log.i(
|
||||||
|
"[Conference Waiting Room] Found our participant, it's role is [${myself.role}]"
|
||||||
|
)
|
||||||
|
val areWeListener = myself.role == Participant.Role.Listener
|
||||||
|
isConferenceBroadcastWithListenerRole.value = areWeListener
|
||||||
|
|
||||||
|
if (areWeListener) {
|
||||||
|
callParams.isVideoEnabled = false
|
||||||
|
callParams.videoDirection = MediaDirection.Inactive
|
||||||
|
updateVideoState()
|
||||||
|
updateLayout()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(
|
||||||
|
"[Conference Waiting Room] Failed to find ourselves in participants info"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(
|
||||||
|
"[Conference Waiting Room] Failed to find conference info using address [$stringAddress]"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e("[Conference Waiting Room] Can't find conference info using null address!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun cancel() {
|
fun cancel() {
|
||||||
cancelConferenceJoiningEvent.value = Event(true)
|
cancelConferenceJoiningEvent.value = Event(true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,16 @@ class ConferencesSettingsViewModel : GenericSettingsViewModel() {
|
||||||
val layoutLabels = MutableLiveData<ArrayList<String>>()
|
val layoutLabels = MutableLiveData<ArrayList<String>>()
|
||||||
private val layoutValues = arrayListOf<Int>()
|
private val layoutValues = arrayListOf<Int>()
|
||||||
|
|
||||||
|
val enableBroadcastListener = object : SettingListenerStub() {
|
||||||
|
override fun onBoolValueChanged(newValue: Boolean) {
|
||||||
|
prefs.disableBroadcastConference = !newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val enableBroadcast = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initLayoutsList()
|
initLayoutsList()
|
||||||
|
enableBroadcast.value = !prefs.disableBroadcastConference
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initLayoutsList() {
|
private fun initLayoutsList() {
|
||||||
|
|
|
@ -34,10 +34,13 @@ class ConferenceParticipantData(
|
||||||
|
|
||||||
val isAdmin = MutableLiveData<Boolean>()
|
val isAdmin = MutableLiveData<Boolean>()
|
||||||
val isMeAdmin = MutableLiveData<Boolean>()
|
val isMeAdmin = MutableLiveData<Boolean>()
|
||||||
|
val isSpeaker = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
isAdmin.value = participant.isAdmin
|
isAdmin.value = participant.isAdmin
|
||||||
isMeAdmin.value = conference.me.isAdmin
|
isMeAdmin.value = conference.me.isAdmin
|
||||||
|
isSpeaker.value = participant.role == Participant.Role.Speaker
|
||||||
|
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Conference Participant] Participant ${participant.address.asStringUriOnly()} is ${if (participant.isAdmin) "admin" else "not admin"}"
|
"[Conference Participant] Participant ${participant.address.asStringUriOnly()} is ${if (participant.isAdmin) "admin" else "not admin"}"
|
||||||
)
|
)
|
||||||
|
|
|
@ -56,9 +56,13 @@ class ConferenceViewModel : ViewModel() {
|
||||||
val twoOrMoreParticipants = MutableLiveData<Boolean>()
|
val twoOrMoreParticipants = MutableLiveData<Boolean>()
|
||||||
val moreThanTwoParticipants = MutableLiveData<Boolean>()
|
val moreThanTwoParticipants = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val speakingParticipantFound = MutableLiveData<Boolean>()
|
||||||
val speakingParticipant = MutableLiveData<ConferenceParticipantDeviceData>()
|
val speakingParticipant = MutableLiveData<ConferenceParticipantDeviceData>()
|
||||||
val meParticipant = MutableLiveData<ConferenceParticipantDeviceData>()
|
val meParticipant = MutableLiveData<ConferenceParticipantDeviceData>()
|
||||||
|
|
||||||
|
val isBroadcast = MutableLiveData<Boolean>()
|
||||||
|
val isMeListenerOnly = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val participantAdminStatusChangedEvent: MutableLiveData<Event<ConferenceParticipantData>> by lazy {
|
val participantAdminStatusChangedEvent: MutableLiveData<Event<ConferenceParticipantData>> by lazy {
|
||||||
MutableLiveData<Event<ConferenceParticipantData>>()
|
MutableLiveData<Event<ConferenceParticipantData>>()
|
||||||
}
|
}
|
||||||
|
@ -207,6 +211,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
speakingParticipant.value?.isActiveSpeaker?.value = false
|
speakingParticipant.value?.isActiveSpeaker?.value = false
|
||||||
device.isActiveSpeaker.value = true
|
device.isActiveSpeaker.value = true
|
||||||
speakingParticipant.value = device!!
|
speakingParticipant.value = device!!
|
||||||
|
speakingParticipantFound.value = true
|
||||||
} else if (device == null) {
|
} else if (device == null) {
|
||||||
Log.w(
|
Log.w(
|
||||||
"[Conference] Participant device [${participantDevice.address.asStringUriOnly()}] is the active speaker but couldn't find it in devices list"
|
"[Conference] Participant device [${participantDevice.address.asStringUriOnly()}] is the active speaker but couldn't find it in devices list"
|
||||||
|
@ -528,6 +533,23 @@ class ConferenceViewModel : ViewModel() {
|
||||||
|
|
||||||
val activelySpeakingParticipantDevice = conference.activeSpeakerParticipantDevice
|
val activelySpeakingParticipantDevice = conference.activeSpeakerParticipantDevice
|
||||||
var foundActivelySpeakingParticipantDevice = false
|
var foundActivelySpeakingParticipantDevice = false
|
||||||
|
speakingParticipantFound.value = false
|
||||||
|
|
||||||
|
val conferenceInfo = conference.core.findConferenceInformationFromUri(
|
||||||
|
conference.conferenceAddress
|
||||||
|
)
|
||||||
|
var allSpeaker = true
|
||||||
|
for (info in conferenceInfo?.participantInfos.orEmpty()) {
|
||||||
|
if (info.role == Participant.Role.Listener) {
|
||||||
|
allSpeaker = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isBroadcast.value = !allSpeaker
|
||||||
|
if (!allSpeaker) {
|
||||||
|
Log.i(
|
||||||
|
"[Conference] Not all participants are speaker, considering it is a broadcast"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
for (participant in participantsList) {
|
for (participant in participantsList) {
|
||||||
val participantDevices = participant.devices
|
val participantDevices = participant.devices
|
||||||
|
@ -539,6 +561,18 @@ class ConferenceViewModel : ViewModel() {
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Conference] Participant device found: ${device.name} (${device.address.asStringUriOnly()})"
|
"[Conference] Participant device found: ${device.name} (${device.address.asStringUriOnly()})"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val info = conferenceInfo?.participantInfos?.find {
|
||||||
|
it.address.weakEqual(participant.address)
|
||||||
|
}
|
||||||
|
if (info != null) {
|
||||||
|
Log.i("[Conference] Participant role is [${info.role.name}]")
|
||||||
|
val listener = info.role == Participant.Role.Listener || info.role == Participant.Role.Unknown
|
||||||
|
if (listener) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val deviceData = ConferenceParticipantDeviceData(device, false)
|
val deviceData = ConferenceParticipantDeviceData(device, false)
|
||||||
devices.add(deviceData)
|
devices.add(deviceData)
|
||||||
|
|
||||||
|
@ -549,6 +583,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
speakingParticipant.value = deviceData
|
speakingParticipant.value = deviceData
|
||||||
deviceData.isActiveSpeaker.value = true
|
deviceData.isActiveSpeaker.value = true
|
||||||
foundActivelySpeakingParticipantDevice = true
|
foundActivelySpeakingParticipantDevice = true
|
||||||
|
speakingParticipantFound.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,12 +595,26 @@ class ConferenceViewModel : ViewModel() {
|
||||||
val deviceData = devices.first()
|
val deviceData = devices.first()
|
||||||
speakingParticipant.value = deviceData
|
speakingParticipant.value = deviceData
|
||||||
deviceData.isActiveSpeaker.value = true
|
deviceData.isActiveSpeaker.value = true
|
||||||
|
speakingParticipantFound.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for (device in conference.me.devices) {
|
for (device in conference.me.devices) {
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Conference] Participant device for myself found: ${device.name} (${device.address.asStringUriOnly()})"
|
"[Conference] Participant device for myself found: ${device.name} (${device.address.asStringUriOnly()})"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val info = conferenceInfo?.participantInfos?.find {
|
||||||
|
it.address.weakEqual(device.address)
|
||||||
|
}
|
||||||
|
if (info != null) {
|
||||||
|
Log.i("[Conference] Me role is [${info.role.name}]")
|
||||||
|
val listener = info.role == Participant.Role.Listener || info.role == Participant.Role.Unknown
|
||||||
|
isMeListenerOnly.value = listener
|
||||||
|
if (listener) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val deviceData = ConferenceParticipantDeviceData(device, true)
|
val deviceData = ConferenceParticipantDeviceData(device, true)
|
||||||
devices.add(deviceData)
|
devices.add(deviceData)
|
||||||
meParticipant.value = deviceData
|
meParticipant.value = deviceData
|
||||||
|
@ -601,6 +650,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
if (speakingParticipant.value == null) {
|
if (speakingParticipant.value == null) {
|
||||||
speakingParticipant.value = deviceData
|
speakingParticipant.value = deviceData
|
||||||
deviceData.isActiveSpeaker.value = true
|
deviceData.isActiveSpeaker.value = true
|
||||||
|
speakingParticipantFound.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
conferenceParticipantDevices.value = sortedDevices
|
conferenceParticipantDevices.value = sortedDevices
|
||||||
|
@ -641,6 +691,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
val deviceData = devices[1]
|
val deviceData = devices[1]
|
||||||
speakingParticipant.value = deviceData
|
speakingParticipant.value = deviceData
|
||||||
deviceData.isActiveSpeaker.value = true
|
deviceData.isActiveSpeaker.value = true
|
||||||
|
speakingParticipantFound.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
conferenceParticipantDevices.value = devices
|
conferenceParticipantDevices.value = devices
|
||||||
|
|
|
@ -377,6 +377,12 @@ class CorePreferences constructor(private val context: Context) {
|
||||||
config.setBool("app", "enter_video_conference_enable_full_screen_mode", value)
|
config.setBool("app", "enter_video_conference_enable_full_screen_mode", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var disableBroadcastConference: Boolean
|
||||||
|
get() = config.getBool("app", "disable_broadcast_conference_feature", true)
|
||||||
|
set(value) {
|
||||||
|
config.setBool("app", "disable_broadcast_conference_feature", value)
|
||||||
|
}
|
||||||
|
|
||||||
/* Assistant */
|
/* Assistant */
|
||||||
|
|
||||||
var firstStart: Boolean
|
var firstStart: Boolean
|
||||||
|
|
9
app/src/main/res/drawable/rect_orange_button.xml
Normal file
9
app/src/main/res/drawable/rect_orange_button.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="false"
|
||||||
|
android:drawable="@drawable/shape_rect_orange_disabled_button" />
|
||||||
|
<item android:state_pressed="true"
|
||||||
|
android:drawable="@drawable/shape_rect_green_button" />
|
||||||
|
<item
|
||||||
|
android:drawable="@drawable/shape_rect_orange_button" />
|
||||||
|
</selector>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<corners android:radius="5dp" />
|
||||||
|
<size android:height="20dp" android:width="20dp"/>
|
||||||
|
<solid android:color="@color/primary_color_disabled"/>
|
||||||
|
</shape>
|
|
@ -166,6 +166,7 @@
|
||||||
android:id="@+id/active_speaker_background"
|
android:id="@+id/active_speaker_background"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
android:visibility="@{conferenceViewModel.speakingParticipantFound ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@id/miniatures"
|
app:layout_constraintEnd_toStartOf="@id/miniatures"
|
||||||
|
@ -179,6 +180,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
|
android:visibility="@{conferenceViewModel.speakingParticipantFound ? View.VISIBLE : View.GONE}"
|
||||||
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
||||||
android:background="@drawable/generated_avatar_bg"
|
android:background="@drawable/generated_avatar_bg"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
|
@ -196,7 +198,7 @@
|
||||||
android:background="@drawable/shape_button_background"
|
android:background="@drawable/shape_button_background"
|
||||||
android:contentDescription="@string/content_description_participant_is_paused"
|
android:contentDescription="@string/content_description_participant_is_paused"
|
||||||
android:src="@drawable/icon_pause"
|
android:src="@drawable/icon_pause"
|
||||||
android:visibility="@{conferenceViewModel.speakingParticipant.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
android:visibility="@{conferenceViewModel.speakingParticipantFound && conferenceViewModel.speakingParticipant.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
app:layout_constraintEnd_toEndOf="@id/active_speaker_background"
|
app:layout_constraintEnd_toEndOf="@id/active_speaker_background"
|
||||||
|
@ -253,6 +255,7 @@
|
||||||
android:id="@+id/local_participant_background"
|
android:id="@+id/local_participant_background"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
android:visibility="@{conferenceViewModel.isMeListenerOnly ? View.GONE : View.VISIBLE}"
|
||||||
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
@ -267,6 +270,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
|
android:visibility="@{conferenceViewModel.isMeListenerOnly ? View.GONE : View.VISIBLE}"
|
||||||
coilSelfAvatar="@{conferenceViewModel.meParticipant}"
|
coilSelfAvatar="@{conferenceViewModel.meParticipant}"
|
||||||
android:background="@drawable/generated_avatar_bg"
|
android:background="@drawable/generated_avatar_bg"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
@ -297,6 +301,7 @@
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
|
android:visibility="@{conferenceViewModel.isMeListenerOnly ? View.GONE : View.VISIBLE}"
|
||||||
android:text="@{conferenceViewModel.meParticipant.contact.name ?? conferenceViewModel.meParticipant.displayName}"
|
android:text="@{conferenceViewModel.meParticipant.contact.name ?? conferenceViewModel.meParticipant.displayName}"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/local_participant_background"
|
app:layout_constraintBottom_toBottomOf="@id/local_participant_background"
|
||||||
app:layout_constraintStart_toStartOf="@id/local_participant_background"
|
app:layout_constraintStart_toStartOf="@id/local_participant_background"
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/conference_invite_title_font"
|
style="@style/conference_invite_title_font"
|
||||||
android:text="@string/conference_invite_title"
|
android:text="@{data.isBroadcast ? @string/conference_broadcast_invite_title : @string/conference_invite_title, default=@string/conference_invite_title}"
|
||||||
android:visibility="@{data.isConferenceUpdated || data.isConferenceCancelled ? View.GONE : View.VISIBLE}"/>
|
android:visibility="@{data.isConferenceUpdated || data.isConferenceCancelled ? View.GONE : View.VISIBLE}"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -67,6 +67,15 @@
|
||||||
android:text="@{data.conferenceParticipantCount, default=`3 participants`}"
|
android:text="@{data.conferenceParticipantCount, default=`3 participants`}"
|
||||||
app:drawableStartCompat="@drawable/icon_schedule_participants"/>
|
app:drawableStartCompat="@drawable/icon_schedule_participants"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="23dp"
|
||||||
|
android:layout_marginBottom="2dp"
|
||||||
|
android:visibility="@{data.isBroadcast && data.isSpeaker ? View.VISIBLE : View.GONE}"
|
||||||
|
style="@style/conference_invite_dat_time_font"
|
||||||
|
android:text="@string/conference_broadcast_invite_you_are_speaker"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
|
@ -118,15 +118,32 @@
|
||||||
android:visibility="@{data.isConferenceCancelled ? View.VISIBLE : View.GONE, default=gone}"
|
android:visibility="@{data.isConferenceCancelled ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
android:text="@{data.canEdit ? @string/conference_scheduled_cancelled_by_me : @string/conference_scheduled_cancelled_by_organizer, default=@string/conference_scheduled_cancelled_by_organizer}"/>
|
android:text="@{data.canEdit ? @string/conference_scheduled_cancelled_by_me : @string/conference_scheduled_cancelled_by_organizer, default=@string/conference_scheduled_cancelled_by_organizer}"/>
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="5dp"
|
android:orientation="horizontal">
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:layout_marginEnd="5dp"
|
<TextView
|
||||||
style="@style/conference_invite_subject_font"
|
android:id="@+id/meeting_type"
|
||||||
android:maxLines="2"
|
android:layout_width="wrap_content"
|
||||||
android:text="@{data.subject, default=`Lorem Ipsum`}"/>
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
style="@style/conference_invite_subject_font"
|
||||||
|
android:text="@{data.isBroadcast() ? @string/conference_broadcast_title : @string/conference_meeting_title, default=@string/conference_meeting_title}"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
style="@style/conference_invite_subject_font"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text="@{data.subject, default=`Lorem Ipsum`}"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:visibility="@{data.expanded ? View.GONE : View.VISIBLE}"
|
android:visibility="@{data.expanded ? View.GONE : View.VISIBLE}"
|
||||||
|
@ -182,24 +199,61 @@
|
||||||
android:contentDescription="@string/content_description_toggle_conference_info_details"
|
android:contentDescription="@string/content_description_toggle_conference_info_details"
|
||||||
android:src="@drawable/button_conference_info" />
|
android:src="@drawable/button_conference_info" />
|
||||||
|
|
||||||
<ImageView
|
<TextView
|
||||||
android:id="@+id/participants_icon"
|
style="@style/conference_invite_desc_font"
|
||||||
|
android:id="@+id/speakers_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:contentDescription="@string/content_description_conference_participants"
|
android:text="@string/conference_invite_speakers_list_title"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="@color/voip_dark_gray"
|
||||||
|
android:drawableStart="@drawable/icon_schedule_participants"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:visibility="@{data.isConferenceCancelled || !data.isBroadcast ? View.GONE : View.VISIBLE}"
|
||||||
|
android:src="@drawable/icon_schedule_participants"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/speakers_list"
|
||||||
|
style="@style/conference_invite_desc_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="23dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_toStartOf="@id/selected_info"
|
||||||
|
android:layout_below="@id/speakers_title"
|
||||||
|
android:background="@color/transparent_color"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:visibility="@{data.isConferenceCancelled || !data.isBroadcast ? View.GONE : View.VISIBLE}"
|
||||||
|
android:text="@{data.speakersExpanded, default=`Daryl Martin\nMartin Pecheur`}"
|
||||||
|
tools:ignore="LabelFor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/conference_invite_desc_font"
|
||||||
|
android:id="@+id/participants_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/speakers_list"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:text="@string/conference_invite_participants_list_title"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="@color/voip_dark_gray"
|
||||||
|
android:drawableStart="@drawable/icon_schedule_participants"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
android:visibility="@{data.isConferenceCancelled ? View.GONE : View.VISIBLE}"
|
android:visibility="@{data.isConferenceCancelled ? View.GONE : View.VISIBLE}"
|
||||||
android:src="@drawable/icon_schedule_participants"/>
|
android:src="@drawable/icon_schedule_participants"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/participants_list"
|
||||||
style="@style/conference_invite_desc_font"
|
style="@style/conference_invite_desc_font"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="23dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_toStartOf="@id/selected_info"
|
android:layout_toStartOf="@id/selected_info"
|
||||||
android:layout_toEndOf="@id/participants_icon"
|
android:layout_below="@id/participants_title"
|
||||||
android:background="@color/transparent_color"
|
android:background="@color/transparent_color"
|
||||||
android:drawablePadding="5dp"
|
android:drawablePadding="5dp"
|
||||||
android:visibility="@{data.isConferenceCancelled ? View.GONE : View.VISIBLE}"
|
android:visibility="@{data.isConferenceCancelled ? View.GONE : View.VISIBLE}"
|
||||||
|
@ -241,7 +295,7 @@
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:visibility="@{data.isConferenceCancelled ? View.GONE : View.VISIBLE}"
|
android:visibility="@{data.isConferenceCancelled ? View.GONE : View.VISIBLE}"
|
||||||
android:text="@string/conference_schedule_address_title"/>
|
android:text="@{data.isBroadcast ? @string/conference_schedule_broadcast_address_title : @string/conference_schedule_address_title, default=@string/conference_schedule_address_title}"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -137,6 +137,31 @@
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="@{viewModel.isBroadcastAllowed ? View.VISIBLE : View.GONE, default=gone}">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/conference_scheduling_font"
|
||||||
|
android:text="@string/conference_schedule_mode"/>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
style="@style/conference_scheduling_font"
|
||||||
|
android:background="@drawable/icon_spinner_background"
|
||||||
|
app:entries="@{viewModel.modesList}"
|
||||||
|
app:selectedValue="@={viewModel.mode}"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/conference_scheduling_participant_cell_height"
|
android:layout_height="@dimen/conference_scheduling_participant_cell_height"
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical"
|
||||||
|
android:background="@color/white_color">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -76,6 +77,17 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:onClick="@{() -> data.changeIsSpeaker()}"
|
||||||
|
android:visibility="@{data.showBroadcastControls ? View.VISIBLE : View.GONE}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@{data.isSpeaker ? @drawable/field_remove : @drawable/field_add, default=@drawable/field_add}"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginEnd="5dp" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
style="@style/calls_list_header_font"
|
style="@style/calls_list_header_font"
|
||||||
android:text="@{viewModel.scheduleForLater ? @string/conference_schedule_summary : @string/conference_group_call_summary, default=@string/conference_group_call_summary}"/>
|
android:text="@{viewModel.isModeBroadcastCurrentlySelected() ? @string/conference_schedule_broadcast_summary : viewModel.scheduleForLater ? @string/conference_schedule_summary : @string/conference_group_call_summary, default=@string/conference_group_call_summary}"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -268,14 +268,49 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
style="@style/conference_scheduling_font"
|
style="@style/conference_scheduling_font"
|
||||||
android:visibility="@{viewModel.scheduleForLater && viewModel.sendInviteViaChat ? View.VISIBLE : View.GONE}"
|
android:visibility="@{viewModel.scheduleForLater && viewModel.sendInviteViaChat ? View.VISIBLE : View.GONE}"
|
||||||
android:text="@string/conference_schedule_send_invite_chat_summary"/>
|
android:text="@string/conference_schedule_send_invite_chat_summary"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{viewModel.isModeBroadcastCurrentlySelected() ? View.VISIBLE : View.GONE}"
|
||||||
|
android:background="?attr/voipFormDisabledFieldBackgroundColor">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
style="@style/calls_list_header_font"
|
||||||
|
android:text="@string/conference_schedule_speakers_list"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="@{viewModel.isModeBroadcastCurrentlySelected() ? View.VISIBLE : View.GONE}"
|
||||||
|
app:entries="@{viewModel.speakersData}"
|
||||||
|
app:layout="@{@layout/conference_scheduling_participant_cell}" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
style="@style/calls_list_header_font"
|
||||||
|
android:textColor="@color/light_grey_color"
|
||||||
|
android:visibility="@{viewModel.isModeBroadcastCurrentlySelected() && viewModel.speakersData.size() == 0 ? View.VISIBLE : View.GONE}"
|
||||||
|
android:text="@string/conference_schedule_speakers_list_empty"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/voipFormDisabledFieldBackgroundColor">
|
android:background="?attr/voipFormDisabledFieldBackgroundColor">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -288,6 +323,16 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
style="@style/calls_list_header_font"
|
||||||
|
android:textColor="@color/light_grey_color"
|
||||||
|
android:visibility="@{viewModel.participantsData.size() == 0 ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
android:text="@string/conference_schedule_participants_list_empty"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -310,10 +355,28 @@
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="@drawable/shape_rect_orange_button"
|
android:background="@drawable/rect_orange_button"
|
||||||
|
android:visibility="@{viewModel.isModeBroadcastCurrentlySelected() ? View.GONE : View.VISIBLE}"
|
||||||
android:text="@{viewModel.isUpdate ? @string/conference_schedule_edit : viewModel.scheduleForLater ? @string/conference_schedule_start : @string/conference_group_call_create, default=@string/conference_group_call_create}"
|
android:text="@{viewModel.isUpdate ? @string/conference_schedule_edit : viewModel.scheduleForLater ? @string/conference_schedule_start : @string/conference_group_call_create, default=@string/conference_group_call_create}"
|
||||||
style="@style/big_orange_button_font"/>
|
style="@style/big_orange_button_font"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:onClick="@{() -> viewModel.createConference()}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="20dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingRight="20dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/rect_orange_button"
|
||||||
|
android:enabled="@{viewModel.participantsData.size() != 0 && viewModel.speakersData.size() != 0}"
|
||||||
|
android:visibility="@{viewModel.isModeBroadcastCurrentlySelected() ? View.VISIBLE : View.GONE, default=gone}"
|
||||||
|
android:text="@{viewModel.isUpdate ? @string/conference_broadcast_edit : @string/conference_broadcast_start, default=@string/conference_broadcast_start}"
|
||||||
|
style="@style/big_orange_button_font"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
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="@{viewModel.isConferenceBroadcastWithListenerRole ? @string/conference_waiting_room_listener_broadcast : @string/conference_waiting_room_video_disabled, default=@string/conference_waiting_room_video_disabled}"
|
||||||
android:visibility="@{viewModel.isVideoEnabled ? View.GONE : View.VISIBLE}" />
|
android:visibility="@{viewModel.isVideoEnabled ? View.GONE : View.VISIBLE}" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
@ -234,7 +234,7 @@
|
||||||
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:contentDescription="@{viewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
||||||
android:enabled="@{!viewModel.joinInProgress}"
|
android:enabled="@{!viewModel.isConferenceBroadcastWithListenerRole && !viewModel.joinInProgress}"
|
||||||
android:onClick="@{() -> viewModel.toggleMuteMicrophone()}"
|
android:onClick="@{() -> viewModel.toggleMuteMicrophone()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{viewModel.isMicrophoneMuted}"
|
android:selected="@{viewModel.isMicrophoneMuted}"
|
||||||
|
@ -284,7 +284,7 @@
|
||||||
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:contentDescription="@{viewModel.isVideoEnabled ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
||||||
android:enabled="@{!viewModel.joinInProgress && viewModel.isVideoAvailable && !viewModel.isLowBandwidth}"
|
android:enabled="@{!viewModel.isConferenceBroadcastWithListenerRole && !viewModel.joinInProgress && viewModel.isVideoAvailable && !viewModel.isLowBandwidth}"
|
||||||
android:onClick="@{() -> viewModel.toggleVideo()}"
|
android:onClick="@{() -> viewModel.toggleVideo()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{viewModel.isVideoEnabled}"
|
android:selected="@{viewModel.isVideoEnabled}"
|
||||||
|
|
|
@ -240,7 +240,6 @@
|
||||||
linphone:title="@{@string/account_setting_conference_factory_address}"
|
linphone:title="@{@string/account_setting_conference_factory_address}"
|
||||||
linphone:listener="@{viewModel.conferenceFactoryUriListener}"
|
linphone:listener="@{viewModel.conferenceFactoryUriListener}"
|
||||||
linphone:defaultValue="@{viewModel.conferenceFactoryUri}"
|
linphone:defaultValue="@{viewModel.conferenceFactoryUri}"
|
||||||
android:visibility="gone"
|
|
||||||
linphone:inputType="@{InputType.TYPE_CLASS_TEXT}"/>
|
linphone:inputType="@{InputType.TYPE_CLASS_TEXT}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
|
@ -248,7 +247,6 @@
|
||||||
linphone:title="@{@string/account_setting_audio_video_conference_factory_address}"
|
linphone:title="@{@string/account_setting_audio_video_conference_factory_address}"
|
||||||
linphone:listener="@{viewModel.audioVideoConferenceFactoryUriListener}"
|
linphone:listener="@{viewModel.audioVideoConferenceFactoryUriListener}"
|
||||||
linphone:defaultValue="@{viewModel.audioVideoConferenceFactoryUri}"
|
linphone:defaultValue="@{viewModel.audioVideoConferenceFactoryUri}"
|
||||||
android:visibility="gone"
|
|
||||||
linphone:inputType="@{InputType.TYPE_CLASS_TEXT}"/>
|
linphone:inputType="@{InputType.TYPE_CLASS_TEXT}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
|
@ -256,7 +254,6 @@
|
||||||
linphone:title="@{@string/account_setting_end_to_end_encryption_keys_server_url}"
|
linphone:title="@{@string/account_setting_end_to_end_encryption_keys_server_url}"
|
||||||
linphone:listener="@{viewModel.limeServerUrlListener}"
|
linphone:listener="@{viewModel.limeServerUrlListener}"
|
||||||
linphone:defaultValue="@{viewModel.limeServerUrl}"
|
linphone:defaultValue="@{viewModel.limeServerUrl}"
|
||||||
android:visibility="gone"
|
|
||||||
linphone:inputType="@{InputType.TYPE_CLASS_TEXT}"/>
|
linphone:inputType="@{InputType.TYPE_CLASS_TEXT}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
|
|
|
@ -72,6 +72,13 @@
|
||||||
linphone:selectedIndex="@{viewModel.layoutIndex}"
|
linphone:selectedIndex="@{viewModel.layoutIndex}"
|
||||||
linphone:labels="@{viewModel.layoutLabels}"/>
|
linphone:labels="@{viewModel.layoutLabels}"/>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/settings_widget_switch"
|
||||||
|
linphone:title="@{@string/conferences_settings_enable_broadcast_title}"
|
||||||
|
linphone:subtitle="@{@string/conferences_settings_enable_broadcast_summary}"
|
||||||
|
linphone:listener="@{viewModel.enableBroadcastListener}"
|
||||||
|
linphone:checked="@={viewModel.enableBroadcast}"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
|
@ -46,10 +46,10 @@
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
android:contentDescription="@{callsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
android:contentDescription="@{callsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
||||||
android:enabled="@{callsViewModel.isMuteMicrophoneEnabled}"
|
android:enabled="@{callsViewModel.isMuteMicrophoneEnabled && !conferenceViewModel.isMeListenerOnly}"
|
||||||
android:onClick="@{() -> callsViewModel.toggleMuteMicrophone()}"
|
android:onClick="@{() -> callsViewModel.toggleMuteMicrophone()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{callsViewModel.isMicrophoneMuted}"
|
android:selected="@{callsViewModel.isMicrophoneMuted || conferenceViewModel.isMeListenerOnly}"
|
||||||
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"
|
||||||
|
@ -96,10 +96,10 @@
|
||||||
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.isSendingVideo ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
android:contentDescription="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
||||||
android:enabled="@{controlsViewModel.isVideoAvailable && !controlsViewModel.isVideoUpdateInProgress}"
|
android:enabled="@{controlsViewModel.isVideoAvailable && !controlsViewModel.isVideoUpdateInProgress && !conferenceViewModel.isMeListenerOnly}"
|
||||||
android:onClick="@{() -> (!conferenceViewModel.conferenceExists || conferenceViewModel.conferenceDisplayMode != ConferenceDisplayMode.AUDIO_ONLY) ? controlsViewModel.toggleVideo() : conferenceViewModel.switchLayoutFromAudioOnlyToActiveSpeaker()}"
|
android:onClick="@{() -> (!conferenceViewModel.conferenceExists || conferenceViewModel.conferenceDisplayMode != ConferenceDisplayMode.AUDIO_ONLY) ? controlsViewModel.toggleVideo() : conferenceViewModel.switchLayoutFromAudioOnlyToActiveSpeaker()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo}"
|
android:selected="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo && !conferenceViewModel.isMeListenerOnly}"
|
||||||
android:visibility="@{controlsViewModel.hideVideo ? View.GONE : View.VISIBLE}"
|
android:visibility="@{controlsViewModel.hideVideo ? View.GONE : View.VISIBLE}"
|
||||||
android:src="@drawable/icon_toggle_camera"
|
android:src="@drawable/icon_toggle_camera"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:onClick="@{() -> controlsViewModel.showNumpad()}"
|
android:onClick="@{() -> controlsViewModel.showNumpad()}"
|
||||||
android:text="@string/call_action_numpad"
|
android:text="@string/call_action_numpad"
|
||||||
|
android:enabled="@{!conferenceViewModel.isBroadcast}"
|
||||||
app:drawableTopCompat="@drawable/icon_call_numpad"
|
app:drawableTopCompat="@drawable/icon_call_numpad"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/chat"
|
app:layout_constraintBottom_toBottomOf="@id/chat"
|
||||||
app:layout_constraintEnd_toStartOf="@id/call_stats"
|
app:layout_constraintEnd_toStartOf="@id/call_stats"
|
||||||
|
@ -175,6 +176,7 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:onClick="@{() -> controlsViewModel.goToCallsList()}"
|
android:onClick="@{() -> controlsViewModel.goToCallsList()}"
|
||||||
android:text="@string/call_action_calls_list"
|
android:text="@string/call_action_calls_list"
|
||||||
|
android:enabled="@{!conferenceViewModel.isBroadcast}"
|
||||||
app:drawableTopCompat="@drawable/icon_calls_list"
|
app:drawableTopCompat="@drawable/icon_calls_list"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
@ -125,6 +125,7 @@
|
||||||
android:id="@+id/active_speaker_background"
|
android:id="@+id/active_speaker_background"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
android:visibility="@{conferenceViewModel.speakingParticipantFound ? View.VISIBLE : View.GONE}"
|
||||||
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
@ -139,6 +140,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
|
android:visibility="@{conferenceViewModel.speakingParticipantFound ? View.VISIBLE : View.GONE}"
|
||||||
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
coilVoipContact="@{conferenceViewModel.speakingParticipant}"
|
||||||
android:background="@drawable/generated_avatar_bg"
|
android:background="@drawable/generated_avatar_bg"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
|
@ -157,7 +159,7 @@
|
||||||
android:background="@drawable/shape_button_background"
|
android:background="@drawable/shape_button_background"
|
||||||
android:contentDescription="@string/content_description_participant_is_paused"
|
android:contentDescription="@string/content_description_participant_is_paused"
|
||||||
android:src="@drawable/icon_pause"
|
android:src="@drawable/icon_pause"
|
||||||
android:visibility="@{conferenceViewModel.speakingParticipant.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
android:visibility="@{conferenceViewModel.speakingParticipantFound && conferenceViewModel.speakingParticipant.isInConference ? View.GONE : View.VISIBLE, default=gone}"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
app:layout_constraintBottom_toBottomOf="@id/active_speaker_background"
|
||||||
app:layout_constraintEnd_toEndOf="@id/active_speaker_background"
|
app:layout_constraintEnd_toEndOf="@id/active_speaker_background"
|
||||||
|
@ -254,6 +256,7 @@
|
||||||
android:id="@+id/local_participant_background"
|
android:id="@+id/local_participant_background"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
android:visibility="@{conferenceViewModel.isMeListenerOnly ? View.GONE : View.VISIBLE}"
|
||||||
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
app:layout_constraintTop_toBottomOf="@id/top_barrier"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
@ -268,6 +271,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
|
android:visibility="@{conferenceViewModel.isMeListenerOnly ? View.GONE : View.VISIBLE}"
|
||||||
coilSelfAvatar="@{conferenceViewModel.meParticipant}"
|
coilSelfAvatar="@{conferenceViewModel.meParticipant}"
|
||||||
android:background="@drawable/generated_avatar_bg"
|
android:background="@drawable/generated_avatar_bg"
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
@ -298,6 +302,7 @@
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
|
android:visibility="@{conferenceViewModel.isMeListenerOnly ? View.GONE : View.VISIBLE}"
|
||||||
android:text="@{conferenceViewModel.meParticipant.contact.name ?? conferenceViewModel.meParticipant.displayName}"
|
android:text="@{conferenceViewModel.meParticipant.contact.name ?? conferenceViewModel.meParticipant.displayName}"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/local_participant_background"
|
app:layout_constraintBottom_toBottomOf="@id/local_participant_background"
|
||||||
app:layout_constraintStart_toStartOf="@id/local_participant_background"
|
app:layout_constraintStart_toStartOf="@id/local_participant_background"
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View"/>
|
||||||
|
<variable
|
||||||
|
name="data"
|
||||||
|
type="org.linphone.activities.voip.data.ConferenceParticipantData" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_width="@dimen/contact_avatar_size"
|
||||||
|
android:layout_height="@dimen/contact_avatar_size"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
coilContact="@{data}"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:background="@drawable/generated_avatar_bg"
|
||||||
|
android:src="@drawable/voip_single_contact_avatar"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/delete"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:contentDescription="@string/content_description_remove_contact_from_chat_room"
|
||||||
|
android:onClick="@{() -> data.removeParticipantFromConference()}"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:src="@drawable/icon_cancel_alt"
|
||||||
|
android:visibility="@{data.isMeAdmin ? View.VISIBLE : View.INVISIBLE}" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/speakerLayout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toStartOf="@id/delete"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:visibility="@{data.isSpeaker ? View.VISIBLE : View.INVISIBLE}">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:contentDescription="@string/content_description_contact_is_speaker"
|
||||||
|
android:src="@drawable/check_selected" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="@string/conference_participants_list_speaker_label"
|
||||||
|
android:textColor="?attr/primaryTextColor" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_toStartOf="@id/speakerLayout"
|
||||||
|
android:layout_toEndOf="@id/avatar"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<org.linphone.views.MarqueeTextView
|
||||||
|
style="@style/contact_name_list_cell_font"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@{data.contact.name ?? data.displayName, default=`Bilbo Baggins`}" />
|
||||||
|
|
||||||
|
<org.linphone.views.MarqueeTextView
|
||||||
|
android:id="@+id/sipUri"
|
||||||
|
style="@style/sip_uri_small_font"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:text="@{data.sipUri, default=`sip:bilbo.baggins@sip.linphone.org`}" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</layout>
|
|
@ -76,7 +76,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:entries="@{conferenceViewModel.conferenceParticipants}"
|
app:entries="@{conferenceViewModel.conferenceParticipants}"
|
||||||
app:layout="@{@layout/voip_conference_participant_cell}" />
|
app:layout="@{conferenceViewModel.isBroadcast ? @layout/voip_conference_participant_broadcast_cell : @layout/voip_conference_participant_cell}" />
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
|
|
@ -799,4 +799,25 @@
|
||||||
<string name="chat_message_many_reactions">%s réactions</string>
|
<string name="chat_message_many_reactions">%s réactions</string>
|
||||||
<string name="conference_invitation_notification_short_desc">invitation à une conférence</string>
|
<string name="conference_invitation_notification_short_desc">invitation à une conférence</string>
|
||||||
<string name="chat_message_voice_recording_notification_short_desc">message vocal</string>
|
<string name="chat_message_voice_recording_notification_short_desc">message vocal</string>
|
||||||
|
<string name="conference_schedule_mode">Mode</string>
|
||||||
|
<string name="conference_schedule_mode_meeting">Réunion</string>
|
||||||
|
<string name="conference_schedule_mode_broadcast">Webinar</string>
|
||||||
|
<string name="conference_schedule_broadcast_summary">Informations du webinar</string>
|
||||||
|
<string name="conference_schedule_speakers_list">Liste des intervenants</string>
|
||||||
|
<string name="conference_schedule_speakers_list_empty">Choisissez au moins un intervenant</string>
|
||||||
|
<string name="conference_schedule_participants_list_empty">Choisissez au moins un participant</string>
|
||||||
|
<string name="conference_broadcast_start">Planifier un webinar</string>
|
||||||
|
<string name="conference_broadcast_edit">Modifier le webinar</string>
|
||||||
|
<string name="conference_meeting_title">Réunion :</string>
|
||||||
|
<string name="conference_broadcast_title">Webinar :</string>
|
||||||
|
<string name="conference_invite_speakers_list_title">Intervenants</string>
|
||||||
|
<string name="conference_invite_participants_list_title">Participants</string>
|
||||||
|
<string name="conference_broadcast_invite_title">Invitation au webinar :</string>
|
||||||
|
<string name="conference_broadcast_invite_you_are_speaker">(vous êtes un intervenant)</string>
|
||||||
|
<string name="conference_schedule_broadcast_address_title">Adresse du webinar</string>
|
||||||
|
<string name="conference_waiting_room_listener_broadcast">Vous n\'êtes pas un intervenant de ce webinar</string>
|
||||||
|
<string name="conferences_settings_enable_broadcast_title">Autoriser les webinar</string>
|
||||||
|
<string name="conferences_settings_enable_broadcast_summary">Fonctionalité encore en béta !</string>
|
||||||
|
<string name="conference_participants_list_speaker_label">Intervenant</string>
|
||||||
|
<string name="content_description_contact_is_speaker">Contact is a speaker</string>
|
||||||
</resources>
|
</resources>
|
|
@ -6,6 +6,7 @@
|
||||||
<!-- You can use https://material.io/design/color/#tools-for-picking-colors to get dark color value from primary -->
|
<!-- You can use https://material.io/design/color/#tools-for-picking-colors to get dark color value from primary -->
|
||||||
<color name="primary_dark_color">#e65000</color>
|
<color name="primary_dark_color">#e65000</color>
|
||||||
<color name="primary_light_color">#ffab4d</color>
|
<color name="primary_light_color">#ffab4d</color>
|
||||||
|
<color name="primary_color_disabled">#4DFE5E00</color> <!-- Try to have a color that renders well on both light & dark theme -->
|
||||||
<color name="notification_led_color">#ff8000</color>
|
<color name="notification_led_color">#ff8000</color>
|
||||||
|
|
||||||
<color name="black_color">#000000</color>
|
<color name="black_color">#000000</color>
|
||||||
|
|
|
@ -274,11 +274,15 @@
|
||||||
<string name="conference_schedule_subject_hint">Meeting subject</string>
|
<string name="conference_schedule_subject_hint">Meeting subject</string>
|
||||||
<string name="conference_group_call_subject_hint">Group call subject</string>
|
<string name="conference_group_call_subject_hint">Group call subject</string>
|
||||||
<string name="conference_schedule_address_title">Meeting address</string>
|
<string name="conference_schedule_address_title">Meeting address</string>
|
||||||
|
<string name="conference_schedule_broadcast_address_title">Broadcast address</string>
|
||||||
<string name="conference_schedule_description_title">Add a description</string>
|
<string name="conference_schedule_description_title">Add a description</string>
|
||||||
<string name="conference_schedule_description_hint">Description</string>
|
<string name="conference_schedule_description_hint">Description</string>
|
||||||
<string name="conference_schedule_date">Date</string>
|
<string name="conference_schedule_date">Date</string>
|
||||||
<string name="conference_schedule_time">Time</string>
|
<string name="conference_schedule_time">Time</string>
|
||||||
<string name="conference_schedule_duration">Duration</string>
|
<string name="conference_schedule_duration">Duration</string>
|
||||||
|
<string name="conference_schedule_mode">Mode</string>
|
||||||
|
<string name="conference_schedule_mode_meeting">Meeting</string>
|
||||||
|
<string name="conference_schedule_mode_broadcast">Broadcast</string>
|
||||||
<string name="conference_schedule_timezone">Timezone</string>
|
<string name="conference_schedule_timezone">Timezone</string>
|
||||||
<string name="conference_schedule_send_invite_chat">Send invite via &appName;</string>
|
<string name="conference_schedule_send_invite_chat">Send invite via &appName;</string>
|
||||||
<string name="conference_schedule_send_updated_invite_chat">Send update via &appName;</string>
|
<string name="conference_schedule_send_updated_invite_chat">Send update via &appName;</string>
|
||||||
|
@ -287,11 +291,17 @@
|
||||||
<string name="conference_schedule_encryption">Would you like to encrypt the meeting?</string>
|
<string name="conference_schedule_encryption">Would you like to encrypt the meeting?</string>
|
||||||
<string name="conference_schedule_send_invite_chat_summary">Invite will be sent out from my &appName; account</string>
|
<string name="conference_schedule_send_invite_chat_summary">Invite will be sent out from my &appName; account</string>
|
||||||
<string name="conference_schedule_participants_list">Participants list</string>
|
<string name="conference_schedule_participants_list">Participants list</string>
|
||||||
|
<string name="conference_schedule_speakers_list">Speakers list</string>
|
||||||
|
<string name="conference_schedule_speakers_list_empty">Select at least one speaker</string>
|
||||||
|
<string name="conference_schedule_participants_list_empty">Select at least one participant</string>
|
||||||
<string name="conference_organizer">Organizer</string>
|
<string name="conference_organizer">Organizer</string>
|
||||||
<string name="conference_schedule_summary">Meeting info</string>
|
<string name="conference_schedule_summary">Meeting info</string>
|
||||||
<string name="conference_group_call_summary">Group call info</string>
|
<string name="conference_group_call_summary">Group call info</string>
|
||||||
|
<string name="conference_schedule_broadcast_summary">Broadcast info</string>
|
||||||
<string name="conference_schedule_start">Schedule meeting</string>
|
<string name="conference_schedule_start">Schedule meeting</string>
|
||||||
<string name="conference_schedule_edit">Edit meeting</string>
|
<string name="conference_schedule_edit">Edit meeting</string>
|
||||||
|
<string name="conference_broadcast_start">Schedule broadcast</string>
|
||||||
|
<string name="conference_broadcast_edit">Edit broadcast</string>
|
||||||
<string name="conference_group_call_create">Start group call</string>
|
<string name="conference_group_call_create">Start group call</string>
|
||||||
<string name="conference_schedule_address_copied_to_clipboard">Meeting address copied into clipboard</string>
|
<string name="conference_schedule_address_copied_to_clipboard">Meeting address copied into clipboard</string>
|
||||||
<string name="conference_schedule_info_not_sent_to_participant">Failed to send meeting info to a participant</string>
|
<string name="conference_schedule_info_not_sent_to_participant">Failed to send meeting info to a participant</string>
|
||||||
|
@ -300,6 +310,8 @@
|
||||||
<string name="conference_default_title">Remote group call</string>
|
<string name="conference_default_title">Remote group call</string>
|
||||||
<string name="conference_local_title">Local group call</string>
|
<string name="conference_local_title">Local group call</string>
|
||||||
<string name="conference_invite_title">Meeting invite:</string>
|
<string name="conference_invite_title">Meeting invite:</string>
|
||||||
|
<string name="conference_broadcast_invite_title">Broadcast invite:</string>
|
||||||
|
<string name="conference_broadcast_invite_you_are_speaker">(you are a speaker)</string>
|
||||||
<string name="conference_update_title">Meeting has been updated:</string>
|
<string name="conference_update_title">Meeting has been updated:</string>
|
||||||
<string name="conference_cancel_title">Meeting has been cancelled:</string>
|
<string name="conference_cancel_title">Meeting has been cancelled:</string>
|
||||||
<string name="conference_description_title">Description</string>
|
<string name="conference_description_title">Description</string>
|
||||||
|
@ -311,6 +323,7 @@
|
||||||
<string name="conference_waiting_room_start_call">Start</string>
|
<string name="conference_waiting_room_start_call">Start</string>
|
||||||
<string name="conference_waiting_room_cancel_call">Cancel</string>
|
<string name="conference_waiting_room_cancel_call">Cancel</string>
|
||||||
<string name="conference_waiting_room_video_disabled">Video is currently disabled</string>
|
<string name="conference_waiting_room_video_disabled">Video is currently disabled</string>
|
||||||
|
<string name="conference_waiting_room_listener_broadcast">You aren\'t a speaker in this broadcast</string>
|
||||||
<string name="conference_scheduled">Meetings</string>
|
<string name="conference_scheduled">Meetings</string>
|
||||||
<string name="conference_layout_too_many_participants_for_mosaic">You can\'t change group call layout as there is too many participants</string>
|
<string name="conference_layout_too_many_participants_for_mosaic">You can\'t change group call layout as there is too many participants</string>
|
||||||
<string name="conference_too_many_participants_for_mosaic_layout">There is too many participants for mosaic layout, switching to active speaker</string>
|
<string name="conference_too_many_participants_for_mosaic_layout">There is too many participants for mosaic layout, switching to active speaker</string>
|
||||||
|
@ -346,6 +359,11 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="conference_scheduled_cancelled_by_organizer">Conference has been cancelled by organizer</string>
|
<string name="conference_scheduled_cancelled_by_organizer">Conference has been cancelled by organizer</string>
|
||||||
<string name="conference_scheduled_cancelled_by_me">You have cancelled the conference</string>
|
<string name="conference_scheduled_cancelled_by_me">You have cancelled the conference</string>
|
||||||
|
<string name="conference_meeting_title">Meeting:</string>
|
||||||
|
<string name="conference_broadcast_title">Broadcast:</string>
|
||||||
|
<string name="conference_invite_speakers_list_title">Speakers</string>
|
||||||
|
<string name="conference_invite_participants_list_title">Participants</string>
|
||||||
|
<string name="conference_participants_list_speaker_label">Speaker</string>
|
||||||
|
|
||||||
<!-- Call -->
|
<!-- Call -->
|
||||||
<string name="call_incoming_title">Incoming Call</string>
|
<string name="call_incoming_title">Incoming Call</string>
|
||||||
|
@ -746,6 +764,8 @@
|
||||||
|
|
||||||
<!-- Conferences settings -->
|
<!-- Conferences settings -->
|
||||||
<string name="conferences_settings_layout_title">Default layout</string>
|
<string name="conferences_settings_layout_title">Default layout</string>
|
||||||
|
<string name="conferences_settings_enable_broadcast_title">Allow broadcasts</string>
|
||||||
|
<string name="conferences_settings_enable_broadcast_summary">Feature currently in beta!</string>
|
||||||
|
|
||||||
<!-- Notifications -->
|
<!-- Notifications -->
|
||||||
<string name="notification_channel_service_id" translatable="false">linphone_notification_service_id</string>
|
<string name="notification_channel_service_id" translatable="false">linphone_notification_service_id</string>
|
||||||
|
@ -851,6 +871,7 @@
|
||||||
<string name="content_description_remove_contact_from_chat_room">Remove contact from conversation</string>
|
<string name="content_description_remove_contact_from_chat_room">Remove contact from conversation</string>
|
||||||
<string name="content_description_contact_is_admin">Contact is an admin in this conversation</string>
|
<string name="content_description_contact_is_admin">Contact is an admin in this conversation</string>
|
||||||
<string name="content_description_contact_is_not_admin">Contact isn\'t an admin in this conversation</string>
|
<string name="content_description_contact_is_not_admin">Contact isn\'t an admin in this conversation</string>
|
||||||
|
<string name="content_description_contact_is_speaker">Contact is a speaker</string>
|
||||||
<string name="content_description_ephemeral_chat_room">Messages are ephemeral in this conversation</string>
|
<string name="content_description_ephemeral_chat_room">Messages are ephemeral in this conversation</string>
|
||||||
<string name="content_description_muted_chat_room">Notifications are disabled for this conversation</string>
|
<string name="content_description_muted_chat_room">Notifications are disabled for this conversation</string>
|
||||||
<string name="content_description_contact_can_do_encryption">Contact can be invited in encrypted conversations</string>
|
<string name="content_description_contact_can_do_encryption">Contact can be invited in encrypted conversations</string>
|
||||||
|
|
Loading…
Reference in a new issue