From 74cd0f1bf86d500bb300a1b9c26624ce4e881cfa Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 19 Aug 2020 17:32:01 +0200 Subject: [PATCH] Added missing call update dialog --- .../call/fragments/ControlsFragment.kt | 29 ++++++++++++ .../call/viewmodels/CallsViewModel.kt | 44 +++++++++++++++---- .../main/viewmodels/DialogViewModel.kt | 13 +++++- app/src/main/res/layout/dialog.xml | 2 +- app/src/main/res/values/strings.xml | 3 ++ 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt b/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt index ce59da057..531530514 100644 --- a/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt +++ b/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt @@ -19,6 +19,7 @@ */ package org.linphone.activities.call.fragments +import android.app.Dialog import android.content.Intent import android.os.Bundle import android.os.SystemClock @@ -28,11 +29,16 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider +import org.linphone.R import org.linphone.activities.call.viewmodels.CallsViewModel import org.linphone.activities.call.viewmodels.ControlsViewModel import org.linphone.activities.call.viewmodels.SharedCallViewModel import org.linphone.activities.main.MainActivity +import org.linphone.activities.main.viewmodels.DialogViewModel +import org.linphone.core.Call import org.linphone.databinding.CallControlsFragmentBinding +import org.linphone.utils.AppUtils +import org.linphone.utils.DialogUtils import org.linphone.utils.Event class ControlsFragment : Fragment() { @@ -79,6 +85,12 @@ class ControlsFragment : Fragment() { } }) + callsViewModel.callUpdateEvent.observe(viewLifecycleOwner, Observer { + it.consume { call -> + showCallUpdateDialog(call) + } + }) + controlsViewModel.chatClickedEvent.observe(viewLifecycleOwner, Observer { it.consume { val intent = Intent() @@ -117,4 +129,21 @@ class ControlsFragment : Fragment() { } }) } + + private fun showCallUpdateDialog(call: Call) { + val viewModel = DialogViewModel(AppUtils.getString(R.string.call_video_update_requested_dialog)) + val dialog: Dialog = DialogUtils.getDialog(requireContext(), viewModel) + + viewModel.showCancelButton({ + callsViewModel.answerCallUpdateRequest(call, false) + dialog.dismiss() + }, getString(R.string.dialog_decline)) + + viewModel.showOkButton({ + callsViewModel.answerCallUpdateRequest(call, true) + dialog.dismiss() + }, getString(R.string.dialog_accept)) + + dialog.show() + } } diff --git a/app/src/main/java/org/linphone/activities/call/viewmodels/CallsViewModel.kt b/app/src/main/java/org/linphone/activities/call/viewmodels/CallsViewModel.kt index 0cf060a4b..79c79e056 100644 --- a/app/src/main/java/org/linphone/activities/call/viewmodels/CallsViewModel.kt +++ b/app/src/main/java/org/linphone/activities/call/viewmodels/CallsViewModel.kt @@ -42,6 +42,10 @@ class CallsViewModel : ViewModel() { MutableLiveData>() } + val callUpdateEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + private val listener = object : CoreListenerStub() { override fun onCallStateChanged( core: Core, @@ -67,17 +71,26 @@ class CallsViewModel : ViewModel() { removeCallFromPausedListIfPresent(call) removeCallFromConferenceIfPresent(call) } + } else if (state == Call.State.Pausing) { + addCallToPausedList(call) + } else if (state == Call.State.Resuming) { + removeCallFromPausedListIfPresent(call) + } else if (call.state == Call.State.UpdatedByRemote) { + // If the correspondent proposes video while audio call, + // defer update until user has chosen whether to accept it or not + val remoteVideo = call.remoteParams?.videoEnabled() ?: false + val localVideo = call.currentParams.videoEnabled() + val autoAccept = call.core.videoActivationPolicy.automaticallyAccept + if (remoteVideo && !localVideo && !autoAccept) { + call.deferUpdate() + // TODO: start 30 secs timer and decline update if no answer when it triggers + callUpdateEvent.value = Event(call) + } } else { - if (state == Call.State.Pausing) { - addCallToPausedList(call) - } else if (state == Call.State.Resuming) { - removeCallFromPausedListIfPresent(call) + if (call.conference != null) { + addCallToConferenceListIfNotAlreadyInIt(call) } else { - if (call.conference != null) { - addCallToConferenceListIfNotAlreadyInIt(call) - } else { - removeCallFromConferenceIfPresent(call) - } + removeCallFromConferenceIfPresent(call) } } } @@ -112,6 +125,19 @@ class CallsViewModel : ViewModel() { super.onCleared() } + fun answerCallUpdateRequest(call: Call, accept: Boolean) { + val core = call.core + val params = core.createCallParams(call) + + if (accept) { + params?.enableVideo(true) + core.enableVideoCapture(true) + core.enableVideoDisplay(true) + } + + call.acceptUpdate(params) + } + fun pauseConference() { if (coreContext.core.isInConference) { coreContext.core.leaveConference() diff --git a/app/src/main/java/org/linphone/activities/main/viewmodels/DialogViewModel.kt b/app/src/main/java/org/linphone/activities/main/viewmodels/DialogViewModel.kt index bc395ae55..68ea7459e 100644 --- a/app/src/main/java/org/linphone/activities/main/viewmodels/DialogViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/viewmodels/DialogViewModel.kt @@ -21,6 +21,8 @@ package org.linphone.activities.main.viewmodels import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import org.linphone.R +import org.linphone.utils.AppUtils class DialogViewModel(val message: String, val title: String = "") : ViewModel() { var showDoNotAskAgain: Boolean = false @@ -45,6 +47,7 @@ class DialogViewModel(val message: String, val title: String = "") : ViewModel() } var showCancel: Boolean = false + var cancelLabel: String = AppUtils.getString(R.string.dialog_cancel) private var onCancel: (Boolean) -> Unit = {} fun showCancelButton(cancel: (Boolean) -> Unit) { @@ -52,12 +55,18 @@ class DialogViewModel(val message: String, val title: String = "") : ViewModel() onCancel = cancel } + fun showCancelButton(cancel: (Boolean) -> Unit, label: String = cancelLabel) { + showCancel = true + onCancel = cancel + cancelLabel = label + } + fun onCancelClicked() { onCancel(doNotAskAgain.value == true) } var showDelete: Boolean = false - var deleteLabel: String = "Delete" + var deleteLabel: String = AppUtils.getString(R.string.dialog_delete) private var onDelete: (Boolean) -> Unit = {} fun showDeleteButton(delete: (Boolean) -> Unit, label: String) { @@ -71,7 +80,7 @@ class DialogViewModel(val message: String, val title: String = "") : ViewModel() } var showOk: Boolean = false - var okLabel: String = "OK" + var okLabel: String = AppUtils.getString(R.string.dialog_ok) private var onOk: (Boolean) -> Unit = {} fun showOkButton(ok: (Boolean) -> Unit, label: String = okLabel) { diff --git a/app/src/main/res/layout/dialog.xml b/app/src/main/res/layout/dialog.xml index 96419e843..e66eea8c7 100644 --- a/app/src/main/res/layout/dialog.xml +++ b/app/src/main/res/layout/dialog.xml @@ -141,7 +141,7 @@ android:background="@drawable/resizable_assistant_button" android:ellipsize="end" android:padding="10dp" - android:text="@string/dialog_cancel" + android:text="@{viewModel.cancelLabel ?? @string/dialog_cancel, default=@string/dialog_cancel}" android:visibility="@{viewModel.showCancel ? View.VISIBLE : View.GONE}" /> Network is unreachable Network error Unknown error + Correspondent would like to turn the video on Audio @@ -553,6 +554,8 @@ Cancel Delete OK + Accept + Decline Call Instant messages are end-to-end encrypted in secured conversations. It is possible to upgrade the security level of a conversation by authenticating participants. To do so, call the contact and follow the authentication process. Operation in progress, please wait