mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-05-03 06:46:25 +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 ->
|
viewModel.isEndToEndEncrypted.observe(viewLifecycleOwner) { encrypted ->
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
binding.eventsList.addItemDecoration(headerItemDecoration)
|
binding.eventsList.addItemDecoration(headerItemDecoration)
|
||||||
|
|
@ -1369,6 +1375,29 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
||||||
dialog.show()
|
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) {
|
private fun openFileInAnotherApp(path: String, mime: String) {
|
||||||
val intent = Intent(Intent.ACTION_VIEW)
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
val contentUri: Uri =
|
val contentUri: Uri =
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,12 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.confirmGroupCallEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume {
|
||||||
|
showConfirmGroupCallPopup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sharedViewModel.listOfSelectedSipUrisEvent.observe(viewLifecycleOwner) {
|
sharedViewModel.listOfSelectedSipUrisEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume { list ->
|
it.consume { list ->
|
||||||
Log.i("$TAG Found [${list.size}] new participants to add to the group, let's do it")
|
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()
|
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) {
|
private fun copyAddressToClipboard(value: String) {
|
||||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
clipboard.setPrimaryClip(ClipData.newPlainText("SIP address", value))
|
clipboard.setPrimaryClip(ClipData.newPlainText("SIP address", value))
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,17 @@ import androidx.annotation.UiThread
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.R
|
||||||
import org.linphone.core.ChatRoom
|
import org.linphone.core.ChatRoom
|
||||||
|
import org.linphone.core.ConferenceScheduler
|
||||||
|
import org.linphone.core.ConferenceSchedulerListenerStub
|
||||||
import org.linphone.core.Factory
|
import org.linphone.core.Factory
|
||||||
|
import org.linphone.core.Participant
|
||||||
|
import org.linphone.core.ParticipantInfo
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.GenericViewModel
|
import org.linphone.ui.GenericViewModel
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
|
||||||
abstract class AbstractConversationViewModel : GenericViewModel() {
|
abstract class AbstractConversationViewModel : GenericViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
@ -38,6 +44,10 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val confirmGroupCallEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
lateinit var chatRoom: ChatRoom
|
lateinit var chatRoom: ChatRoom
|
||||||
|
|
||||||
lateinit var localSipUri: String
|
lateinit var localSipUri: String
|
||||||
|
|
@ -48,6 +58,47 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
|
||||||
return ::chatRoom.isInitialized
|
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
|
@WorkerThread
|
||||||
open fun beforeNotifyingChatRoomFound(sameOne: Boolean) {
|
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.Address
|
||||||
import org.linphone.core.ChatRoom
|
import org.linphone.core.ChatRoom
|
||||||
import org.linphone.core.ChatRoomListenerStub
|
import org.linphone.core.ChatRoomListenerStub
|
||||||
import org.linphone.core.ConferenceScheduler
|
|
||||||
import org.linphone.core.ConferenceSchedulerListenerStub
|
|
||||||
import org.linphone.core.EventLog
|
import org.linphone.core.EventLog
|
||||||
import org.linphone.core.Factory
|
import org.linphone.core.Factory
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
import org.linphone.core.Participant
|
import org.linphone.core.Participant
|
||||||
import org.linphone.core.ParticipantInfo
|
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.chat.model.ParticipantModel
|
import org.linphone.ui.main.chat.model.ParticipantModel
|
||||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
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 {
|
private val contactsListener = object : ContactsManager.ContactsListener {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override fun onContactsLoaded() {
|
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
|
@UiThread
|
||||||
fun scheduleMeeting() {
|
fun scheduleMeeting() {
|
||||||
coreContext.postOnCoreThread {
|
coreContext.postOnCoreThread {
|
||||||
|
|
@ -637,42 +575,6 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
||||||
participants.postValue(participantsList)
|
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
|
@WorkerThread
|
||||||
private fun getParticipant(eventLog: EventLog): String {
|
private fun getParticipant(eventLog: EventLog): String {
|
||||||
val participantAddress = eventLog.participantAddress
|
val participantAddress = eventLog.participantAddress
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,8 @@ import org.linphone.core.ChatMessageReaction
|
||||||
import org.linphone.core.ChatRoom
|
import org.linphone.core.ChatRoom
|
||||||
import org.linphone.core.ChatRoom.HistoryFilter
|
import org.linphone.core.ChatRoom.HistoryFilter
|
||||||
import org.linphone.core.ChatRoomListenerStub
|
import org.linphone.core.ChatRoomListenerStub
|
||||||
import org.linphone.core.ConferenceScheduler
|
|
||||||
import org.linphone.core.ConferenceSchedulerListenerStub
|
|
||||||
import org.linphone.core.EventLog
|
import org.linphone.core.EventLog
|
||||||
import org.linphone.core.Factory
|
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
import org.linphone.core.Participant
|
|
||||||
import org.linphone.core.ParticipantInfo
|
|
||||||
import org.linphone.core.SearchDirection
|
import org.linphone.core.SearchDirection
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.chat.model.EventLogModel
|
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 {
|
private val contactsListener = object : ContactsManager.ContactsListener {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override fun onContactsLoaded() {
|
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
|
@UiThread
|
||||||
fun markAsRead() {
|
fun markAsRead() {
|
||||||
coreContext.postOnCoreThread {
|
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
|
@UiThread
|
||||||
fun copyFileToUri(filePath: String, dest: Uri) {
|
fun copyFileToUri(filePath: String, dest: Uri) {
|
||||||
val source = Uri.parse(FileUtils.getProperFilePath(filePath))
|
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.DialogRemoveCallLogsBinding
|
||||||
import org.linphone.databinding.DialogRemoveConversationHistoryBinding
|
import org.linphone.databinding.DialogRemoveConversationHistoryBinding
|
||||||
import org.linphone.databinding.DialogSetOrEditGroupSubjectBindingImpl
|
import org.linphone.databinding.DialogSetOrEditGroupSubjectBindingImpl
|
||||||
|
import org.linphone.databinding.DialogStartGroupCallFromConversationBinding
|
||||||
import org.linphone.databinding.DialogUpdateAccountPasswordAfterRegisterFailureBinding
|
import org.linphone.databinding.DialogUpdateAccountPasswordAfterRegisterFailureBinding
|
||||||
import org.linphone.databinding.DialogUpdateAccountPasswordBinding
|
import org.linphone.databinding.DialogUpdateAccountPasswordBinding
|
||||||
import org.linphone.databinding.DialogUpdateAvailableBinding
|
import org.linphone.databinding.DialogUpdateAvailableBinding
|
||||||
|
|
@ -281,6 +282,22 @@ class DialogUtils {
|
||||||
return getDialog(context, binding)
|
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
|
@UiThread
|
||||||
fun getDeleteConversationHistoryConfirmationDialog(
|
fun getDeleteConversationHistoryConfirmationDialog(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,7 @@
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="40dp"
|
android:layout_marginTop="40dp"
|
||||||
android:background="@drawable/circle_light_blue_button_background"
|
android:background="@drawable/circle_light_blue_button_background"
|
||||||
android:onClick="@{() -> viewModel.call()}"
|
android:onClick="@{() -> viewModel.startCall()}"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:src="@drawable/phone"
|
android:src="@drawable/phone"
|
||||||
android:contentDescription="@string/content_description_call_start"
|
android:contentDescription="@string/content_description_call_start"
|
||||||
|
|
@ -240,7 +240,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:onClick="@{() -> viewModel.call()}"
|
android:onClick="@{() -> viewModel.startCall()}"
|
||||||
android:text="@string/conversation_action_call"
|
android:text="@string/conversation_action_call"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:visibility="@{viewModel.isReadOnly ? View.GONE : View.VISIBLE}"
|
android:visibility="@{viewModel.isReadOnly ? View.GONE : View.VISIBLE}"
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="15dp"
|
android:layout_marginEnd="15dp"
|
||||||
android:enabled="@{!viewModel.emptySubject}"
|
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_constraintStart_toStartOf="@id/dialog_background"
|
||||||
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cancel"
|
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_marginTop="16dp"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="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_constraintStart_toStartOf="@id/dialog_background"
|
||||||
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cancel"
|
app:layout_constraintTop_toBottomOf="@id/cancel"
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="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_constraintStart_toStartOf="@id/dialog_background"
|
||||||
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
app:layout_constraintEnd_toEndOf="@id/dialog_background"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cancel"
|
app:layout_constraintTop_toBottomOf="@id/cancel"
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
<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>
|
<string name="dialog_remove">Retirer</string>
|
||||||
|
<string name="dialog_confirm">Confirmer</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>
|
||||||
|
|
@ -444,7 +445,6 @@
|
||||||
<string name="conversation_dialog_edit_subject">Renommer la conversation</string>
|
<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_cant_be_empty_error">Un nom est obligatoire</string>
|
||||||
<string name="conversation_dialog_subject_hint">Nom de la conversation</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_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_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>
|
<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_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_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_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_created">Vous avez rejoint le groupe</string>
|
||||||
<string name="conversation_event_conference_destroyed">Vous avez quitté 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_no">No</string>
|
||||||
<string name="dialog_yes">Yes</string>
|
<string name="dialog_yes">Yes</string>
|
||||||
<string name="dialog_remove">Remove</string>
|
<string name="dialog_remove">Remove</string>
|
||||||
|
<string name="dialog_confirm">Confirm</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>
|
||||||
|
|
@ -482,7 +483,6 @@
|
||||||
<string name="conversation_dialog_edit_subject">Edit conversation subject</string>
|
<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_cant_be_empty_error">Subject is mandatory</string>
|
||||||
<string name="conversation_dialog_subject_hint">Conversation subject</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_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_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>
|
<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_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_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_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_created">You have joined the group</string>
|
||||||
<string name="conversation_event_conference_destroyed">You have left the group</string>
|
<string name="conversation_event_conference_destroyed">You have left the group</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue