mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-29 23:26:25 +00:00
Added dialog to confirm removing a participant from conference
This commit is contained in:
parent
79961739e0
commit
fdafcfd7a4
7 changed files with 209 additions and 8 deletions
|
|
@ -29,11 +29,14 @@ import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
|
import org.linphone.core.Participant
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.CallConferenceParticipantsListFragmentBinding
|
import org.linphone.databinding.CallConferenceParticipantsListFragmentBinding
|
||||||
import org.linphone.ui.call.adapter.ConferenceParticipantsListAdapter
|
import org.linphone.ui.call.adapter.ConferenceParticipantsListAdapter
|
||||||
import org.linphone.ui.call.fragment.GenericCallFragment
|
import org.linphone.ui.call.fragment.GenericCallFragment
|
||||||
import org.linphone.ui.call.viewmodel.CurrentCallViewModel
|
import org.linphone.ui.call.viewmodel.CurrentCallViewModel
|
||||||
|
import org.linphone.ui.main.history.model.ConfirmationDialogModel
|
||||||
|
import org.linphone.utils.DialogUtils
|
||||||
|
|
||||||
class ConferenceParticipantsListFragment : GenericCallFragment() {
|
class ConferenceParticipantsListFragment : GenericCallFragment() {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
@ -102,5 +105,38 @@ class ConferenceParticipantsListFragment : GenericCallFragment() {
|
||||||
Log.i("$TAG participants list updated with [${it.size}] items")
|
Log.i("$TAG participants list updated with [${it.size}] items")
|
||||||
adapter.submitList(it)
|
adapter.submitList(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.conferenceModel.removeParticipantEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume { pair ->
|
||||||
|
val displayName = pair.first
|
||||||
|
val participant = pair.second
|
||||||
|
showKickParticipantDialog(displayName, participant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showKickParticipantDialog(displayName: String, participant: Participant) {
|
||||||
|
val model = ConfirmationDialogModel()
|
||||||
|
val dialog = DialogUtils.getKickConferenceParticipantConfirmationDialog(
|
||||||
|
requireActivity(),
|
||||||
|
model,
|
||||||
|
displayName
|
||||||
|
)
|
||||||
|
|
||||||
|
model.dismissEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model.confirmEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
viewModel.conferenceModel.kickParticipant(participant)
|
||||||
|
// TODO: notify participant was kicked out
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,12 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.core.Participant
|
import org.linphone.core.Participant
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
|
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||||
|
|
||||||
class ConferenceParticipantModel @WorkerThread constructor(
|
class ConferenceParticipantModel @WorkerThread constructor(
|
||||||
val participant: Participant,
|
val participant: Participant,
|
||||||
val isMyselfAdmin: Boolean,
|
val avatarModel: ContactAvatarModel,
|
||||||
|
isMyselfAdmin: Boolean,
|
||||||
val isMyself: Boolean,
|
val isMyself: Boolean,
|
||||||
private val removeFromConference: ((participant: Participant) -> Unit)?,
|
private val removeFromConference: ((participant: Participant) -> Unit)?,
|
||||||
private val changeAdminStatus: ((participant: Participant, setAdmin: Boolean) -> Unit)?
|
private val changeAdminStatus: ((participant: Participant, setAdmin: Boolean) -> Unit)?
|
||||||
|
|
@ -39,10 +41,6 @@ class ConferenceParticipantModel @WorkerThread constructor(
|
||||||
|
|
||||||
val sipUri = participant.address.asStringUriOnly()
|
val sipUri = participant.address.asStringUriOnly()
|
||||||
|
|
||||||
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
|
||||||
participant.address
|
|
||||||
)
|
|
||||||
|
|
||||||
val isAdmin = MutableLiveData<Boolean>()
|
val isAdmin = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val isMeAdmin = MutableLiveData<Boolean>()
|
val isMeAdmin = MutableLiveData<Boolean>()
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@ class ConferenceViewModel {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val removeParticipantEvent: MutableLiveData<Event<Pair<String, Participant>>> by lazy {
|
||||||
|
MutableLiveData<Event<Pair<String, Participant>>>()
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var conference: Conference
|
private lateinit var conference: Conference
|
||||||
|
|
||||||
private val conferenceListener = object : ConferenceListenerStub() {
|
private val conferenceListener = object : ConferenceListenerStub() {
|
||||||
|
|
@ -311,6 +315,16 @@ class ConferenceViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
fun kickParticipant(participant: Participant) {
|
||||||
|
coreContext.postOnCoreThread {
|
||||||
|
Log.i(
|
||||||
|
"$TAG Kicking participant [${participant.address.asStringUriOnly()}] out of conference"
|
||||||
|
)
|
||||||
|
conference.removeParticipant(participant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun setNewLayout(newLayout: Int) {
|
fun setNewLayout(newLayout: Int) {
|
||||||
val call = conference.call
|
val call = conference.call
|
||||||
|
|
@ -408,12 +422,18 @@ class ConferenceViewModel {
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Participant [${participant.address.asStringUriOnly()}] has [${devices.size}] devices and role [${role.name}]"
|
"$TAG Participant [${participant.address.asStringUriOnly()}] has [${devices.size}] devices and role [${role.name}]"
|
||||||
)
|
)
|
||||||
|
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||||
|
participant.address
|
||||||
|
)
|
||||||
val participantModel = ConferenceParticipantModel(
|
val participantModel = ConferenceParticipantModel(
|
||||||
participant,
|
participant,
|
||||||
|
avatarModel,
|
||||||
admin,
|
admin,
|
||||||
false,
|
false,
|
||||||
{ participant -> // Remove from conference
|
{ participant -> // Remove from conference
|
||||||
conference.removeParticipant(participant)
|
removeParticipantEvent.postValue(
|
||||||
|
Event(Pair(avatarModel.name.value.orEmpty(), participant))
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{ participant, setAdmin -> // Change admin status
|
{ participant, setAdmin -> // Change admin status
|
||||||
conference.setParticipantAdminStatus(participant, setAdmin)
|
conference.setParticipantAdminStatus(participant, setAdmin)
|
||||||
|
|
@ -443,7 +463,17 @@ class ConferenceViewModel {
|
||||||
"$TAG [${devicesList.size}] participant devices for [${participantsList.size}] participants will be displayed (not counting ourselves)"
|
"$TAG [${devicesList.size}] participant devices for [${participantsList.size}] participants will be displayed (not counting ourselves)"
|
||||||
)
|
)
|
||||||
|
|
||||||
val meParticipantModel = ConferenceParticipantModel(meParticipant, admin, true, null, null)
|
val meAvatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||||
|
meParticipant.address
|
||||||
|
)
|
||||||
|
val meParticipantModel = ConferenceParticipantModel(
|
||||||
|
meParticipant,
|
||||||
|
meAvatarModel,
|
||||||
|
admin,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
participantsList.add(meParticipantModel)
|
participantsList.add(meParticipantModel)
|
||||||
|
|
||||||
val ourDevices = conference.me.devices
|
val ourDevices = conference.me.devices
|
||||||
|
|
@ -558,12 +588,18 @@ class ConferenceViewModel {
|
||||||
val list = arrayListOf<ConferenceParticipantModel>()
|
val list = arrayListOf<ConferenceParticipantModel>()
|
||||||
list.addAll(participants.value.orEmpty())
|
list.addAll(participants.value.orEmpty())
|
||||||
|
|
||||||
|
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||||
|
participant.address
|
||||||
|
)
|
||||||
val newModel = ConferenceParticipantModel(
|
val newModel = ConferenceParticipantModel(
|
||||||
participant,
|
participant,
|
||||||
|
avatarModel,
|
||||||
isMeAdmin.value == true,
|
isMeAdmin.value == true,
|
||||||
false,
|
false,
|
||||||
{ participant -> // Remove from conference
|
{ participant -> // Remove from conference
|
||||||
conference.removeParticipant(participant)
|
removeParticipantEvent.postValue(
|
||||||
|
Event(Pair(avatarModel.name.value.orEmpty(), participant))
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{ participant, setAdmin -> // Change admin status
|
{ participant, setAdmin -> // Change admin status
|
||||||
conference.setParticipantAdminStatus(participant, setAdmin)
|
conference.setParticipantAdminStatus(participant, setAdmin)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import org.linphone.databinding.DialogConfirmZrtpSasBinding
|
||||||
import org.linphone.databinding.DialogContactConfirmTrustCallBinding
|
import org.linphone.databinding.DialogContactConfirmTrustCallBinding
|
||||||
import org.linphone.databinding.DialogContactTrustProcessBinding
|
import org.linphone.databinding.DialogContactTrustProcessBinding
|
||||||
import org.linphone.databinding.DialogDeleteContactBinding
|
import org.linphone.databinding.DialogDeleteContactBinding
|
||||||
|
import org.linphone.databinding.DialogKickFromConferenceBinding
|
||||||
import org.linphone.databinding.DialogManageAccountInternationalPrefixHelpBinding
|
import org.linphone.databinding.DialogManageAccountInternationalPrefixHelpBinding
|
||||||
import org.linphone.databinding.DialogMergeCallsIntoConferenceBinding
|
import org.linphone.databinding.DialogMergeCallsIntoConferenceBinding
|
||||||
import org.linphone.databinding.DialogPickNumberOrAddressBinding
|
import org.linphone.databinding.DialogPickNumberOrAddressBinding
|
||||||
|
|
@ -355,6 +356,27 @@ class DialogUtils {
|
||||||
return getDialog(context, binding)
|
return getDialog(context, binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun getKickConferenceParticipantConfirmationDialog(
|
||||||
|
context: Context,
|
||||||
|
viewModel: ConfirmationDialogModel,
|
||||||
|
displayName: String
|
||||||
|
): Dialog {
|
||||||
|
val binding: DialogKickFromConferenceBinding = DataBindingUtil.inflate(
|
||||||
|
LayoutInflater.from(context),
|
||||||
|
R.layout.dialog_kick_from_conference,
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
binding.title.text = context.getString(
|
||||||
|
R.string.conference_confirm_removing_participant_dialog_title,
|
||||||
|
displayName
|
||||||
|
)
|
||||||
|
|
||||||
|
return getDialog(context, binding)
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
fun getCancelMeetingDialog(
|
fun getCancelMeetingDialog(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
|
||||||
103
app/src/main/res/layout/dialog_kick_from_conference.xml
Normal file
103
app/src/main/res/layout/dialog_kick_from_conference.xml
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<import type="android.view.View" />
|
||||||
|
<import type="android.graphics.Typeface" />
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="org.linphone.ui.main.history.model.ConfirmationDialogModel" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:onClick="@{() -> viewModel.dismiss()}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/dialog_background"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:layout_marginBottom="2dp"
|
||||||
|
android:src="@drawable/shape_dialog_background"
|
||||||
|
app:layout_constraintWidth_max="@dimen/dialog_max_width"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/anchor"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/title" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/section_header_style"
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:paddingTop="@dimen/dialog_top_bottom_margin"
|
||||||
|
android:text="@string/conference_confirm_removing_participant_dialog_title"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/message"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
style="@style/default_text_style"
|
||||||
|
android:id="@+id/message"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:layout_marginEnd="15dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="@string/conference_confirm_removing_participant_dialog_message"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/cancel"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:onClick="@{() -> viewModel.dismiss()}"
|
||||||
|
style="@style/secondary_button_label_style"
|
||||||
|
android:id="@+id/cancel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:layout_marginEnd="15dp"
|
||||||
|
android:text="@string/dialog_cancel"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/message"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/confirm"/>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:onClick="@{() -> viewModel.confirm()}"
|
||||||
|
style="@style/primary_button_label_style"
|
||||||
|
android:id="@+id/confirm"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:layout_marginEnd="15dp"
|
||||||
|
android:text="@string/dialog_remove"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/cancel"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/anchor"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/anchor"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/dialog_top_bottom_margin"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/confirm"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</layout>
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
<string name="dialog_do_not_show_anymore">Ne plus me montrer ce message</string>
|
<string name="dialog_do_not_show_anymore">Ne plus me montrer ce message</string>
|
||||||
<string name="dialog_no">Non</string>
|
<string name="dialog_no">Non</string>
|
||||||
<string name="dialog_yes">Oui</string>
|
<string name="dialog_yes">Oui</string>
|
||||||
|
<string name="dialog_remove">Retirer</string>
|
||||||
|
|
||||||
<!-- Related to Android notifications -->
|
<!-- Related to Android notifications -->
|
||||||
<string name="notification_channel_call_name">&appName; notifications d\'appels en cours</string>
|
<string name="notification_channel_call_name">&appName; notifications d\'appels en cours</string>
|
||||||
|
|
@ -585,6 +586,8 @@
|
||||||
<item quantity="one">%s participant</item>
|
<item quantity="one">%s participant</item>
|
||||||
<item quantity="other">%s participants</item>
|
<item quantity="other">%s participants</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="conference_confirm_removing_participant_dialog_title">Retirer %s de la conférence ?</string>
|
||||||
|
<string name="conference_confirm_removing_participant_dialog_message">Voulez-vous vraiment retirer ce participant de la conférence ?</string>
|
||||||
<string name="conference_participant_joining_text">En train de rejoindre…</string>
|
<string name="conference_participant_joining_text">En train de rejoindre…</string>
|
||||||
<string name="conference_participant_paused_text">En pause</string>
|
<string name="conference_participant_paused_text">En pause</string>
|
||||||
<string name="conference_active_speaker_is_screen_sharing">partage son écran</string>
|
<string name="conference_active_speaker_is_screen_sharing">partage son écran</string>
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@
|
||||||
<string name="dialog_do_not_show_anymore">Do not show this dialog anymore</string>
|
<string name="dialog_do_not_show_anymore">Do not show this dialog anymore</string>
|
||||||
<string name="dialog_no">No</string>
|
<string name="dialog_no">No</string>
|
||||||
<string name="dialog_yes">Yes</string>
|
<string name="dialog_yes">Yes</string>
|
||||||
|
<string name="dialog_remove">Remove</string>
|
||||||
|
|
||||||
<!-- Related to Android notifications -->
|
<!-- Related to Android notifications -->
|
||||||
<string name="notification_channel_call_name">&appName; active calls notifications</string>
|
<string name="notification_channel_call_name">&appName; active calls notifications</string>
|
||||||
|
|
@ -621,6 +622,8 @@
|
||||||
<item quantity="one">%s participant</item>
|
<item quantity="one">%s participant</item>
|
||||||
<item quantity="other">%s participants</item>
|
<item quantity="other">%s participants</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="conference_confirm_removing_participant_dialog_title">Remove %s from conference?</string>
|
||||||
|
<string name="conference_confirm_removing_participant_dialog_message">Are you sure you want to remove this participant from the conference?</string>
|
||||||
<string name="conference_participant_joining_text">Joining…</string>
|
<string name="conference_participant_joining_text">Joining…</string>
|
||||||
<string name="conference_participant_paused_text">Paused</string>
|
<string name="conference_participant_paused_text">Paused</string>
|
||||||
<string name="conference_active_speaker_is_screen_sharing">is sharing it\'s screen</string>
|
<string name="conference_active_speaker_is_screen_sharing">is sharing it\'s screen</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue