mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 03:18:06 +00:00
Added confirmation dialog before starting a group call from a group conversation
This commit is contained in:
parent
eaa498f1ad
commit
63cb7d6630
13 changed files with 299 additions and 203 deletions
|
|
@ -512,6 +512,12 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.confirmGroupCallEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
showConfirmGroupCallPopup()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.isEndToEndEncrypted.observe(viewLifecycleOwner) { encrypted ->
|
||||
if (encrypted) {
|
||||
binding.eventsList.addItemDecoration(headerItemDecoration)
|
||||
|
|
@ -1369,6 +1375,29 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
|||
dialog.show()
|
||||
}
|
||||
|
||||
private fun showConfirmGroupCallPopup() {
|
||||
val model = ConfirmationDialogModel()
|
||||
val dialog = DialogUtils.getConfirmGroupCallDialog(
|
||||
requireActivity(),
|
||||
model
|
||||
)
|
||||
|
||||
model.dismissEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
model.confirmEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
viewModel.startGroupCall()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun openFileInAnotherApp(path: String, mime: String) {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
val contentUri: Uri =
|
||||
|
|
|
|||
|
|
@ -184,6 +184,12 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.confirmGroupCallEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
showConfirmGroupCallPopup()
|
||||
}
|
||||
}
|
||||
|
||||
sharedViewModel.listOfSelectedSipUrisEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { list ->
|
||||
Log.i("$TAG Found [${list.size}] new participants to add to the group, let's do it")
|
||||
|
|
@ -428,6 +434,29 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
dialog.show()
|
||||
}
|
||||
|
||||
private fun showConfirmGroupCallPopup() {
|
||||
val model = ConfirmationDialogModel()
|
||||
val dialog = DialogUtils.getConfirmGroupCallDialog(
|
||||
requireActivity(),
|
||||
model
|
||||
)
|
||||
|
||||
model.dismissEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
model.confirmEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
viewModel.startGroupCall()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun copyAddressToClipboard(value: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText("SIP address", value))
|
||||
|
|
|
|||
|
|
@ -23,11 +23,17 @@ import androidx.annotation.UiThread
|
|||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.ConferenceScheduler
|
||||
import org.linphone.core.ConferenceSchedulerListenerStub
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.Participant
|
||||
import org.linphone.core.ParticipantInfo
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.GenericViewModel
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
abstract class AbstractConversationViewModel : GenericViewModel() {
|
||||
companion object {
|
||||
|
|
@ -38,6 +44,10 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val confirmGroupCallEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
lateinit var chatRoom: ChatRoom
|
||||
|
||||
lateinit var localSipUri: String
|
||||
|
|
@ -48,6 +58,47 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
|
|||
return ::chatRoom.isInitialized
|
||||
}
|
||||
|
||||
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
|
||||
override fun onStateChanged(
|
||||
conferenceScheduler: ConferenceScheduler,
|
||||
state: ConferenceScheduler.State
|
||||
) {
|
||||
Log.i("$TAG Conference scheduler state is $state")
|
||||
if (state == ConferenceScheduler.State.Ready) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
|
||||
val conferenceAddress = conferenceScheduler.info?.uri
|
||||
if (conferenceAddress != null) {
|
||||
Log.i(
|
||||
"$TAG Conference info created, address is ${conferenceAddress.asStringUriOnly()}"
|
||||
)
|
||||
coreContext.startVideoCall(conferenceAddress)
|
||||
} else {
|
||||
Log.e("$TAG Conference info URI is null!")
|
||||
showRedToastEvent.postValue(
|
||||
Event(
|
||||
Pair(
|
||||
R.string.conference_failed_to_create_group_call_toast,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} else if (state == ConferenceScheduler.State.Error) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
Log.e("$TAG Failed to create group call!")
|
||||
showRedToastEvent.postValue(
|
||||
Event(
|
||||
Pair(
|
||||
R.string.conference_failed_to_create_group_call_toast,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
open fun beforeNotifyingChatRoomFound(sameOne: Boolean) {
|
||||
}
|
||||
|
|
@ -128,4 +179,59 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startCall() {
|
||||
coreContext.postOnCoreThread {
|
||||
if (LinphoneUtils.isChatRoomAGroup(chatRoom) && chatRoom.participants.size >= 2) {
|
||||
confirmGroupCallEvent.postValue(Event(true))
|
||||
} else {
|
||||
val firstParticipant = chatRoom.participants.firstOrNull()
|
||||
val address = firstParticipant?.address
|
||||
if (address != null) {
|
||||
Log.i("$TAG Audio calling SIP address [${address.asStringUriOnly()}]")
|
||||
coreContext.startAudioCall(address)
|
||||
} else {
|
||||
Log.e("$TAG Failed to find participant to call!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startGroupCall() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val account = core.defaultAccount
|
||||
if (account == null) {
|
||||
Log.e(
|
||||
"$TAG No default account found, can't create group call!"
|
||||
)
|
||||
return@postOnCoreThread
|
||||
}
|
||||
|
||||
val conferenceInfo = Factory.instance().createConferenceInfo()
|
||||
conferenceInfo.organizer = account.params.identityAddress
|
||||
conferenceInfo.subject = chatRoom.subject
|
||||
|
||||
val participants = arrayOfNulls<ParticipantInfo>(chatRoom.participants.size)
|
||||
var index = 0
|
||||
for (participant in chatRoom.participants) {
|
||||
val info = Factory.instance().createParticipantInfo(participant.address)
|
||||
// For meetings, all participants must have Speaker role
|
||||
info?.role = Participant.Role.Speaker
|
||||
participants[index] = info
|
||||
index += 1
|
||||
}
|
||||
conferenceInfo.setParticipantInfos(participants)
|
||||
|
||||
Log.i(
|
||||
"$TAG Creating group call with subject ${conferenceInfo.subject} and ${participants.size} participant(s)"
|
||||
)
|
||||
val conferenceScheduler = core.createConferenceScheduler()
|
||||
conferenceScheduler.addListener(conferenceSchedulerListener)
|
||||
conferenceScheduler.account = account
|
||||
// Will trigger the conference creation/update automatically
|
||||
conferenceScheduler.info = conferenceInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,10 @@ import org.linphone.contacts.ContactsManager
|
|||
import org.linphone.core.Address
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.ChatRoomListenerStub
|
||||
import org.linphone.core.ConferenceScheduler
|
||||
import org.linphone.core.ConferenceSchedulerListenerStub
|
||||
import org.linphone.core.EventLog
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.Participant
|
||||
import org.linphone.core.ParticipantInfo
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.chat.model.ParticipantModel
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
|
|
@ -196,47 +193,6 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
}
|
||||
}
|
||||
|
||||
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
|
||||
override fun onStateChanged(
|
||||
conferenceScheduler: ConferenceScheduler,
|
||||
state: ConferenceScheduler.State
|
||||
) {
|
||||
Log.i("$TAG Conference scheduler state is $state")
|
||||
if (state == ConferenceScheduler.State.Ready) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
|
||||
val conferenceAddress = conferenceScheduler.info?.uri
|
||||
if (conferenceAddress != null) {
|
||||
Log.i(
|
||||
"$TAG Conference info created, address is ${conferenceAddress.asStringUriOnly()}"
|
||||
)
|
||||
coreContext.startVideoCall(conferenceAddress)
|
||||
} else {
|
||||
Log.e("$TAG Conference info URI is null!")
|
||||
showRedToastEvent.postValue(
|
||||
Event(
|
||||
Pair(
|
||||
R.string.conference_failed_to_create_group_call_toast,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} else if (state == ConferenceScheduler.State.Error) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
Log.e("$TAG Failed to create group call!")
|
||||
showRedToastEvent.postValue(
|
||||
Event(
|
||||
Pair(
|
||||
R.string.conference_failed_to_create_group_call_toast,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val contactsListener = object : ContactsManager.ContactsListener {
|
||||
@WorkerThread
|
||||
override fun onContactsLoaded() {
|
||||
|
|
@ -304,24 +260,6 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun call() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (LinphoneUtils.isChatRoomAGroup(chatRoom) && chatRoom.participants.size >= 2) {
|
||||
createGroupCall()
|
||||
} else {
|
||||
val firstParticipant = chatRoom.participants.firstOrNull()
|
||||
val address = firstParticipant?.address
|
||||
if (address != null) {
|
||||
Log.i("$TAG Audio calling SIP address [${address.asStringUriOnly()}]")
|
||||
coreContext.startAudioCall(address)
|
||||
} else {
|
||||
Log.e("$TAG Failed to find participant to call!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun scheduleMeeting() {
|
||||
coreContext.postOnCoreThread {
|
||||
|
|
@ -637,42 +575,6 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
participants.postValue(participantsList)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun createGroupCall() {
|
||||
val core = coreContext.core
|
||||
val account = core.defaultAccount
|
||||
if (account == null) {
|
||||
Log.e(
|
||||
"$TAG No default account found, can't create group call!"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val conferenceInfo = Factory.instance().createConferenceInfo()
|
||||
conferenceInfo.organizer = account.params.identityAddress
|
||||
conferenceInfo.subject = subject.value
|
||||
|
||||
val participants = arrayOfNulls<ParticipantInfo>(chatRoom.participants.size)
|
||||
var index = 0
|
||||
for (participant in chatRoom.participants) {
|
||||
val info = Factory.instance().createParticipantInfo(participant.address)
|
||||
// For meetings, all participants must have Speaker role
|
||||
info?.role = Participant.Role.Speaker
|
||||
participants[index] = info
|
||||
index += 1
|
||||
}
|
||||
conferenceInfo.setParticipantInfos(participants)
|
||||
|
||||
Log.i(
|
||||
"$TAG Creating group call with subject ${subject.value} and ${participants.size} participant(s)"
|
||||
)
|
||||
val conferenceScheduler = core.createConferenceScheduler()
|
||||
conferenceScheduler.addListener(conferenceSchedulerListener)
|
||||
conferenceScheduler.account = account
|
||||
// Will trigger the conference creation/update automatically
|
||||
conferenceScheduler.info = conferenceInfo
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getParticipant(eventLog: EventLog): String {
|
||||
val participantAddress = eventLog.participantAddress
|
||||
|
|
|
|||
|
|
@ -36,13 +36,8 @@ import org.linphone.core.ChatMessageReaction
|
|||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.ChatRoom.HistoryFilter
|
||||
import org.linphone.core.ChatRoomListenerStub
|
||||
import org.linphone.core.ConferenceScheduler
|
||||
import org.linphone.core.ConferenceSchedulerListenerStub
|
||||
import org.linphone.core.EventLog
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.Participant
|
||||
import org.linphone.core.ParticipantInfo
|
||||
import org.linphone.core.SearchDirection
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.chat.model.EventLogModel
|
||||
|
|
@ -281,47 +276,6 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo
|
|||
}
|
||||
}
|
||||
|
||||
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
|
||||
override fun onStateChanged(
|
||||
conferenceScheduler: ConferenceScheduler,
|
||||
state: ConferenceScheduler.State
|
||||
) {
|
||||
Log.i("$TAG Conference scheduler state is $state")
|
||||
if (state == ConferenceScheduler.State.Ready) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
|
||||
val conferenceAddress = conferenceScheduler.info?.uri
|
||||
if (conferenceAddress != null) {
|
||||
Log.i(
|
||||
"$TAG Conference info created, address is ${conferenceAddress.asStringUriOnly()}"
|
||||
)
|
||||
coreContext.startVideoCall(conferenceAddress)
|
||||
} else {
|
||||
Log.e("$TAG Conference info URI is null!")
|
||||
showRedToastEvent.postValue(
|
||||
Event(
|
||||
Pair(
|
||||
R.string.conference_failed_to_create_group_call_toast,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
} else if (state == ConferenceScheduler.State.Error) {
|
||||
conferenceScheduler.removeListener(this)
|
||||
Log.e("$TAG Failed to create group call!")
|
||||
showRedToastEvent.postValue(
|
||||
Event(
|
||||
Pair(
|
||||
R.string.conference_failed_to_create_group_call_toast,
|
||||
R.drawable.warning_circle
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val contactsListener = object : ContactsManager.ContactsListener {
|
||||
@WorkerThread
|
||||
override fun onContactsLoaded() {
|
||||
|
|
@ -463,22 +417,6 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startCall() {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (LinphoneUtils.isChatRoomAGroup(chatRoom) && chatRoom.participants.size >= 2) {
|
||||
createGroupCall()
|
||||
} else {
|
||||
val firstParticipant = chatRoom.participants.firstOrNull()
|
||||
val address = firstParticipant?.address
|
||||
if (address != null) {
|
||||
Log.i("$TAG Audio calling SIP address [${address.asStringUriOnly()}]")
|
||||
coreContext.startAudioCall(address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun markAsRead() {
|
||||
coreContext.postOnCoreThread {
|
||||
|
|
@ -987,42 +925,6 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun createGroupCall() {
|
||||
val core = coreContext.core
|
||||
val account = core.defaultAccount
|
||||
if (account == null) {
|
||||
Log.e(
|
||||
"$TAG No default account found, can't create group call!"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val conferenceInfo = Factory.instance().createConferenceInfo()
|
||||
conferenceInfo.organizer = account.params.identityAddress
|
||||
conferenceInfo.subject = subject.value
|
||||
|
||||
val participants = arrayOfNulls<ParticipantInfo>(chatRoom.participants.size)
|
||||
var index = 0
|
||||
for (participant in chatRoom.participants) {
|
||||
val info = Factory.instance().createParticipantInfo(participant.address)
|
||||
// For meetings, all participants must have Speaker role
|
||||
info?.role = Participant.Role.Speaker
|
||||
participants[index] = info
|
||||
index += 1
|
||||
}
|
||||
conferenceInfo.setParticipantInfos(participants)
|
||||
|
||||
Log.i(
|
||||
"$TAG Creating group call with subject ${subject.value} and ${participants.size} participant(s)"
|
||||
)
|
||||
val conferenceScheduler = core.createConferenceScheduler()
|
||||
conferenceScheduler.addListener(conferenceSchedulerListener)
|
||||
conferenceScheduler.account = account
|
||||
// Will trigger the conference creation/update automatically
|
||||
conferenceScheduler.info = conferenceInfo
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun copyFileToUri(filePath: String, dest: Uri) {
|
||||
val source = Uri.parse(FileUtils.getProperFilePath(filePath))
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import org.linphone.databinding.DialogRemoveAllCallLogsBinding
|
|||
import org.linphone.databinding.DialogRemoveCallLogsBinding
|
||||
import org.linphone.databinding.DialogRemoveConversationHistoryBinding
|
||||
import org.linphone.databinding.DialogSetOrEditGroupSubjectBindingImpl
|
||||
import org.linphone.databinding.DialogStartGroupCallFromConversationBinding
|
||||
import org.linphone.databinding.DialogUpdateAccountPasswordAfterRegisterFailureBinding
|
||||
import org.linphone.databinding.DialogUpdateAccountPasswordBinding
|
||||
import org.linphone.databinding.DialogUpdateAvailableBinding
|
||||
|
|
@ -281,6 +282,22 @@ class DialogUtils {
|
|||
return getDialog(context, binding)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun getConfirmGroupCallDialog(
|
||||
context: Context,
|
||||
viewModel: ConfirmationDialogModel
|
||||
): Dialog {
|
||||
val binding: DialogStartGroupCallFromConversationBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(context),
|
||||
R.layout.dialog_start_group_call_from_conversation,
|
||||
null,
|
||||
false
|
||||
)
|
||||
binding.viewModel = viewModel
|
||||
|
||||
return getDialog(context, binding)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun getDeleteConversationHistoryConfirmationDialog(
|
||||
context: Context,
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@
|
|||
android:layout_height="56dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:background="@drawable/circle_light_blue_button_background"
|
||||
android:onClick="@{() -> viewModel.call()}"
|
||||
android:onClick="@{() -> viewModel.startCall()}"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/phone"
|
||||
android:contentDescription="@string/content_description_call_start"
|
||||
|
|
@ -240,7 +240,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:onClick="@{() -> viewModel.call()}"
|
||||
android:onClick="@{() -> viewModel.startCall()}"
|
||||
android:text="@string/conversation_action_call"
|
||||
android:textSize="14sp"
|
||||
android:visibility="@{viewModel.isReadOnly ? View.GONE : View.VISIBLE}"
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@
|
|||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:enabled="@{!viewModel.emptySubject}"
|
||||
android:text="@string/conversation_dialog_edit_subject_confirm_button"
|
||||
android:text="@string/dialog_confirm"
|
||||
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||
app:layout_constraintTop_toBottomOf="@id/cancel"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<variable
|
||||
name="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"
|
||||
android:contentDescription="@null"
|
||||
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/conversation_info_confirm_start_group_call_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/conversation_info_confirm_start_group_call_dialog_message"
|
||||
android:textSize="14sp"
|
||||
android:autoLink="web"
|
||||
android:textColorLink="?attr/color_main1_500"
|
||||
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_confirm"
|
||||
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>
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
android:layout_marginTop="16dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:text="@string/conversation_dialog_edit_subject_confirm_button"
|
||||
android:text="@string/dialog_confirm"
|
||||
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||
app:layout_constraintTop_toBottomOf="@id/cancel"
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@
|
|||
android:layout_marginTop="16dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:text="@string/conversation_dialog_edit_subject_confirm_button"
|
||||
android:text="@string/dialog_confirm"
|
||||
app:layout_constraintStart_toStartOf="@id/dialog_background"
|
||||
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||
app:layout_constraintTop_toBottomOf="@id/cancel"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
<string name="dialog_no">Non</string>
|
||||
<string name="dialog_yes">Oui</string>
|
||||
<string name="dialog_remove">Retirer</string>
|
||||
<string name="dialog_confirm">Confirmer</string>
|
||||
|
||||
<!-- Related to Android notifications -->
|
||||
<string name="notification_channel_call_name">&appName; notifications d\'appels en cours</string>
|
||||
|
|
@ -444,7 +445,6 @@
|
|||
<string name="conversation_dialog_edit_subject">Renommer la conversation</string>
|
||||
<string name="conversation_dialog_subject_cant_be_empty_error">Un nom est obligatoire</string>
|
||||
<string name="conversation_dialog_subject_hint">Nom de la conversation</string>
|
||||
<string name="conversation_dialog_edit_subject_confirm_button">Confirmer</string>
|
||||
<string name="conversation_dialog_open_or_export_file_title">Ouvrir ou sauvegarder le fichier ?</string>
|
||||
<string name="conversation_dialog_open_or_export_file_message">&appName; ne peut ouvrir ce fichier.\n\nVoulez-vous l\'ouvrir dans une autre app (si possible), ou le sauvegarder sur votre appareil ?</string>
|
||||
<string name="conversation_dialog_open_file_label">Ouvrir le fichier</string>
|
||||
|
|
@ -485,6 +485,9 @@
|
|||
<string name="conversation_info_participant_no_longer_has_admin_rights_toast">%s is no longer admin</string>
|
||||
<string name="conversation_info_cant_find_contact_to_display_toast">Contact non trouvé</string>
|
||||
<string name="conversation_info_no_address_to_add_to_contact_toast">Aucune adresse à ajouter au contact</string>
|
||||
<string name="conversation_info_confirm_start_group_call_dialog_title">Démarrer un appel de groupe ?</string>
|
||||
<string name="conversation_info_confirm_start_group_call_dialog_message">Tous les participants de la conversation recevront un appel.</string>
|
||||
<string name="conversation_info_confirm_start_group_call_dialog_button">Démarrer l\'appel de groupe</string>
|
||||
|
||||
<string name="conversation_event_conference_created">Vous avez rejoint le groupe</string>
|
||||
<string name="conversation_event_conference_destroyed">Vous avez quitté le groupe</string>
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@
|
|||
<string name="dialog_no">No</string>
|
||||
<string name="dialog_yes">Yes</string>
|
||||
<string name="dialog_remove">Remove</string>
|
||||
<string name="dialog_confirm">Confirm</string>
|
||||
|
||||
<!-- Related to Android notifications -->
|
||||
<string name="notification_channel_call_name">&appName; active calls notifications</string>
|
||||
|
|
@ -482,7 +483,6 @@
|
|||
<string name="conversation_dialog_edit_subject">Edit conversation subject</string>
|
||||
<string name="conversation_dialog_subject_cant_be_empty_error">Subject is mandatory</string>
|
||||
<string name="conversation_dialog_subject_hint">Conversation subject</string>
|
||||
<string name="conversation_dialog_edit_subject_confirm_button">Confirm</string>
|
||||
<string name="conversation_dialog_open_or_export_file_title">Open or export file?</string>
|
||||
<string name="conversation_dialog_open_or_export_file_message">&appName; can\'t open this file.\n\nDo you want to open it in another app (if possible), or export it on your device?</string>
|
||||
<string name="conversation_dialog_open_file_label">Open file</string>
|
||||
|
|
@ -523,6 +523,9 @@
|
|||
<string name="conversation_info_participant_no_longer_has_admin_rights_toast">%s is no longer admin</string>
|
||||
<string name="conversation_info_cant_find_contact_to_display_toast">Contact was not found</string>
|
||||
<string name="conversation_info_no_address_to_add_to_contact_toast">No address to add to contact</string>
|
||||
<string name="conversation_info_confirm_start_group_call_dialog_title">Start a group call?</string>
|
||||
<string name="conversation_info_confirm_start_group_call_dialog_message">All participants will receive a call.</string>
|
||||
<string name="conversation_info_confirm_start_group_call_dialog_button">Start a group call</string>
|
||||
|
||||
<string name="conversation_event_conference_created">You have joined the group</string>
|
||||
<string name="conversation_event_conference_destroyed">You have left the group</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue